【C++ 】C++ 与 C#:using 关键字、命名空间及作用域解析符对比

C++ vs C#:using、命名空间、.::的一图三句速查

速查表(建议收藏)
特性 C++ C# 记忆口诀
引入整个命名空间 using namespace std; using System; 一样写
引入单个名字 using std::cout; ❌ 不支持 变量进类
类型别名 using Map = std::map<K,V>; using Map = Dictionary<K,V>; 右侧糖
作用域运算符 ::(能指全局) .(始终前缀) 双冒变点

1. using关键字:同名不同命

1.1 C++ 的三张面孔

cpp 复制代码
// ① 整包引入
#include <iostream>
using namespace std;          // 整包

// ② 精确引入
using std::cout;              // 单名
using std::endl;

// ③ 类型别名
#include <vector>
using IntVec = vector<int>;   // 别名

int main() {
    IntVec v{1,2,3};
    cout << v.size() << endl; // 单名引入,无需 std::
}

1.2 C# 的两张面孔

csharp 复制代码
// ① 整包引入
using System;
using System.Collections.Generic;

// ② 静态导入(整包静态成员)
using static System.Math;     // 只能"类"级,不能"单名"

class Program {
    static void Main() {
        Console.WriteLine(Sqrt(9)); // 直接 Sqrt
    }
}

1.3 反例:C# 没有"单名引入"

csharp 复制代码
namespace N {
    public static class Foo {
        public static void Bar() { }
    }
}

// 理想:using N.Foo.Bar;   // ❌ CS0138
// 现实:using static N.Foo; // √ 但 Bar 以外全进来

2. 命名空间:能放啥?

2.1 C++ ------ 什么都敢放

cpp 复制代码
namespace My {
    int       g = 42;           // 变量
    void foo() { }              // 函数
    class Cls { };              // 类型
}

int main() {
    My::foo();                  // 直接调
}

2.2 C# ------ 只能放"类型"

csharp 复制代码
namespace My {
    // int g;                   // ❌ CS0116
    // void foo() { }           // ❌ CS0116
    public static class Globals { // 变量进类
        public static int G = 42;
    }
}

class Program {
    static void Main() {
        Console.WriteLine(My.Globals.G);
    }
}

3. 作用域运算符::: vs .

C++任何名字前面只要出现 ::,编译器就进入"绝对路径"模式:从最外层作用域 开始一路找下去,中间可以跨命名空间、类、枚举、typedef/别名、模板 等。

下面把 :: 的 6 个高频场景一次列全,并给出"如果写成 . 会怎样"的对照,方便 C++ → C# 迁移时一眼看出差异。


  1. 全球定位:跳过局部遮蔽
cpp 复制代码
int value = 1;
void foo() {
    int value = 2;
    std::cout << ::value;   // 1,强制用全局
}

  1. 命名空间逐级下降
cpp 复制代码
namespace A::B {           // C++17 嵌套写法
    int x = 5;
}
int main() {
    std::cout << A::B::x;  // 5
}

C# 等价只能一路 .A.B.x


  1. 类/结构体静态成员
cpp 复制代码
struct Math {
    static double pi;
};
double Math::pi = 3.14;    // 类外定义时必须写 ::

C# 把静态成员直接写在类体里,访问时也是 .


  1. 嵌套类型(最常见的就是 iterator
cpp 复制代码
std::vector<int>::iterator it = v.begin();   // iterator 是 vector<int> 内部的类型别名

换成 C# 写法:

csharp 复制代码
List<int>.Enumerator it = v.GetEnumerator(); // 同样嵌套,但用 `.`

  1. 枚举类强作用域
cpp 复制代码
enum class Color { Red, Green };
Color c = Color::Red;        // 必须 ::

C# 枚举仍然是"弱作用域",直接 Color.Red


  1. 模板特化/静态断言等"编译期路径"
cpp 复制代码
template<typename T>
struct Foo {
    using type = T*;
};

Foo<int>::type p = nullptr;  // 取嵌套别名
static_assert(sizeof(Foo<double>::type) == 8);

C# 泛型没有 :: 语法,嵌套类型一律 .


一句话总结
:: 是 C++ 的"绝对路径分隔符",凡是需要从外层作用域开始精确寻名 的场景都会出现;

C# 没有"全局作用域"概念,也没有运算符重载之外的"类外定义"需求,因此统一用 . 即可。


4. 冷知识:编译器看谁

  • C++ 的 using 别名在模板实例化阶段仍可见;
  • C# 的 using 别名在生成 IL 时会被完全擦除,反射拿到的是原长名。

相关推荐
hez20102 小时前
在 .NET 上构建超大托管数组
c#·.net·.net core·gc·clr
见过夏天6 小时前
C++ 基础入门完全指南
c++
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境3 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
卷无止境3 天前
OpenMPI、MPICH 与 OpenMP:关系、核心概念与架构全解
c++·后端
郝学胜_神的一滴4 天前
CMake 30:循环语法全解|foreach_while双循环精讲、迭代技巧与实战避坑指南
c++·cmake
雨落倾城夏未凉5 天前
第四章c#方法-参数数组和可选参数(16)
后端·c#
卷无止境6 天前
C++ 的Eigen 库全解析
c++
卷无止境6 天前
现代 C++特性大盘点:一门脱胎换骨的老语言
c++·后端