C++基础
1. 命名空间
1.1 namespace的价值
在C/C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称如果都存在于全局作用域中,可能会导致很多冲突。使⽤命名空间的⽬的是对标识符的名称进⾏本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的
c语⾔项⽬类似下⾯程序这样的命名冲突是普遍存在的问题,C++引⼊namespace就是为了更好的解决这样的问题
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main() {
// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”
printf("%d\n", rand);
return 0;
}
1.2 namespace的定义
-
定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
-
namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量,所以下⾯的rand不在冲突了。
#include <stdio.h> #include <stdlib.h> namespace abc { // 变量 int rand = 10; // 函数 int Add(int a, int b) { return a + b; } // 类型 struct Node { int val; struct Node* next; } } int main() { // 指定访问abc中的rand // ::称为域作用限定符 printf("%d\n", abc::rand); return 0; }
-
C++中的域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/类型出处(声明或定义)的逻辑,所以有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的⽣命周期,命名空间域和类域不影响变量⽣命周期。
-
namespace只能定义在全局,当然他还可以嵌套定义。
// 嵌套定义
#include <iostream>
namespace A
{
namespace B
{
int rand = 1;
int func(int a, int b) {
return a + b;
}
}
namespace C
{
int rand = 2;
int func(int a, int b) {
return a - b;
}
}
}
// 引用语法如下
int main() {
std::cout << "A::B::rand -> " << A::B::rand << std::endl;
std::cout << "A::C::rand -> " << A::C::rand << std::endl;
std::cout << "A::B::func(1,2) -> " << A::B::func(1, 2) << std::endl;
std::cout << "A::C::func(1,2) -> " << A::C::func(1, 2) << std::endl;
return 0;
}
- 项⽬⼯程中多⽂件中定义的同名namespace会认为是⼀个namespace,合并到一起,不会冲突。
- C++标准库都放在⼀个叫std(standard)的命名空间中。
1.3 命名空间使用
编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下面程序会编译报错。
#include <stdio.h>
namespace A
{
int a = 0;
int b = 1;
}
int main() {
// 编译报错:error C2065 : “a”:未声明的标识符
printf("%d\n", a);
return 0;
}
所以我们要使⽤命名空间中定义的变量/函数,有三种⽅式:
-
指定命名空间访问,项⽬中推荐这种⽅式
#include <stdio.h> namespace A { int a = 0; int b = 1; } int main() { // 指定命名空间访问 printf("%d\n", A::a); return 0; }
-
using将命名空间中某个成员展开&#x