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# 迁移时一眼看出差异。
- 全球定位:跳过局部遮蔽
cpp
int value = 1;
void foo() {
int value = 2;
std::cout << ::value; // 1,强制用全局
}
- 命名空间逐级下降
cpp
namespace A::B { // C++17 嵌套写法
int x = 5;
}
int main() {
std::cout << A::B::x; // 5
}
C# 等价只能一路 .: A.B.x
- 类/结构体
静态成员
cpp
struct Math {
static double pi;
};
double Math::pi = 3.14; // 类外定义时必须写 ::
C# 把静态成员直接写在类体里,访问时也是 .
- 嵌套类型(最常见的就是
iterator)
cpp
std::vector<int>::iterator it = v.begin(); // iterator 是 vector<int> 内部的类型别名
换成 C# 写法:
csharp
List<int>.Enumerator it = v.GetEnumerator(); // 同样嵌套,但用 `.`
- 枚举类强作用域
cpp
enum class Color { Red, Green };
Color c = Color::Red; // 必须 ::
C# 枚举仍然是"弱作用域",直接 Color.Red
- 模板特化/静态断言等"编译期路径"
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 时会被完全擦除,反射拿到的是原长名。