C++关键字&&命名空间
近段时间学习了C++的相关内容, C++还是很火的编程语言!下面分享我的学习心得:关于C++关键字和命名空间的认识
1.C++关键字
C++总计63个关键字,C语言32个关键字
asm | do | if | return | try | continue |
---|---|---|---|---|---|
auto | double | inline | short | typedef | for |
bool | dynamic_cast | int | signed | typeid | public |
break | else | long | sizeof | typename | throw |
case | enum | mutable | static | union | wchar_t |
catch | explicit | namespace | static_cast | unsigned | default |
char | export | new | struct | using | friend |
class | extern | operator | switch | virtual | register |
const | false | private | template | void | true |
const_cast | float | protected | this | volatile | while |
delete | goto | reinterpret_cast |
2.命名空间
为什么存在
主要是为了为了解决命名冲突
例子:
#include<stdio.h> #include<stdlib.h>//里面包含rand函数 int rand = 0;//全局变量rand int main() { printf("rand = %d\n", rand);//编译器不知道打印的是函数的地址(函数名 == 函数的地址)还是全局变量rand的值 printf("%d\n",rand());//这样没问题,这样相当于是调用rand函数 return 0; }
若rand为全局变量则有问题了,因为rand函数和rand变量都是全局变量,编译器不知道哪个是你要打印的是哪个
但是写成这样没问题:
#include<stdio.h> #include<stdlib.h> int main() { int rand = 0;//此时的rand变量为局部变量,局部优先, printf("rand = %d\n", rand);//0 局部优先,打印的是局部变量rand的值 return 0; }0
此时rand为局部变量就没有问题,全局变量和局部变量可以同名,使用时原则为:局部优先(先使用局部变量)
编译器寻找变量的规则是:先在该作用域中寻找该局部变量,找不到再去全局变量中找,如果还是找不到,就会报错
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的,
- 使用命名空间后
#include<stdio.h> #include<stdlib.h> namespace M_Space//定义一个叫M_Space的命名空间-域 { int rand = 0; } int a = 10; int main() { printf("rand = %d\n", rand); // :: 域作用限定符 printf("命名空间的rand = %d\n", M_Space::rand);//表示rand再M_Space这个域中寻找 M_Space::rand = 10; printf("修改值后:命名空间的rand = %d\n", M_Space::rand); printf("%d\n" , ::a);//10 //若域作用限定符的坐标是空白,则说明再全局域中寻找 return 0; }
命名空间的定义
命名空间是全局的,命名空间里面的成员也是全局的变量
定义命名空间需要使用到
namespace关键字
,后面跟命名空间的名字,然后接一对{},{}中即为命名空间的成员
- 例子
namespace MS //MS是命名空间的名字 - 域 { int a = 0;//a是全局变量,放在静态区,是MS命名空间的成员, }
域中的成员变量是不能在域中赋值的!只能初始化时候赋初始值
命名空间中的内容,既可以定义变量,也可以定义函数,也可以创建类型(结构体,联合体..)
namespace M_Space { int a = 0; int Add(int x, int y) { return x +y ; } struct Student { int age; char sex[7]; }; }
- 命名空间中的结构体使用时的注意事项
namespace M_Space { struct Student { int age; char sex[7]; }; } M_Space::struct Student stu;//err struct M_Space::Student stu;//写法1 M_Space::Student stu;//写法2
- 命名空间内部的变量可以定义时初始化,但是不可以在命名空间内再次赋值,要再次赋值要在其它函数内赋值
namespace M_Space { int a = 0;//定义时初始化 int b;//只定义不初始化 a = 10;//err b = 5;//err } M_Space::a = 10;//err 在外部赋值也不可以,要在函数内部赋值 void test() { M_Space :: a = 10;//可以 }
原因分析:
命名空间内创建的是全局变量,全局变量要在函数内部赋值,初始化时只能赋初始值
int a = 10; a = 20;//err int main() { a = 10;//OK return 0; }
2.命名空间可以嵌套
namespace N1 { int a = 2; namespace N2 { int b = 3; } } int main() { N1::a = 2; N1::N2::b = 1; //同样也是使用::域作用限定符进行逐层访问 printf("a = %d b = %d\n", N1::a, N1::N2::b);// 2 1 return 0; }
3.同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中,
namespace N1 { int a = 0; int b = 2; } namespace N1 { int a = 1; } int main() { printf("a = %d b = %d\n", N1::a, N1::b); return 0; }
相同名称的命名空间,最后会合成同一个命名空间中,所以相同名称的命名空间里面的成员名字不能相同,否则会报错
命名空间不影响变量的属性,它还是全局变量,只是影响了编译器找该变量的规则
命名空间里面可以只放声明(函数声明)
命名空间的使用
方法1:加命名空间名称及作用域限定符 ::
命名空间名称 :: 成员名;
namespace M1 { int a = 10; } int main() { printf("before:M1::a = %d\n", M1::a);//10 M1::a = 20; printf("after:M1::a = %d\n", M1::a);//20 return 0; }
优缺点:
- 优点:不会造成命名污染 缺点:使用麻烦
方法2:使用using将命名空间中成员引入
using 命名空间名称 :: 要展开的成员;
namespace M1 { int a = 10; int b = 20; } //单独展开M1中的a变量,其它不展开 using M1::a; int main() { printf("a = %d\n", a);//10 printf("b = %d\n", b);//b未被引入,编译器找不到,会报错 return 0; }
想要程序没问题:把b也展开
using M1::a; using M1::b;
方法3:使用using namespace命名空间名称引入
using namespace 命名空间名称 ;
这种写法是直接把整个命名空间展开,使用方便,但是命名空间的隔离作用就失效了
namespace M1 { int a = 10; int b = 20; } //把M1这个命名空间展开-展开到全局 using namespace M1; int main() { printf("a = %d\n", a);//10 printf("b = %d\n", b);//20 return 0; }
namespace N1 { int a = 2; namespace N2 { int a = 3; } } using namespace N1; int a = 0; int main() { //printf("a = %d ", a);//err,未知要打印的是N1的成员变量a还是外部的全局变量a printf("a = %d ", N1::a);//这样使用了域限定符就可以 return 0; }
命名空间N1展开之后,N1里面的全局变量a和外部的全局变量a重名了,N1失去了隔离作用
优缺点:
- 优点: 使用成员方便
- 缺点:由于是展开到全局,如果全局也有相同名字变量或函数名等,会造成命名污染,编译器报错