2022-04-29-
摘要
总结
目录
C++关键字
C++关键字全集(参考 C++ Primer ):
asm | auto | bad _cast | bad _typeid |
---|---|---|---|
bool | break | case | catch |
char | class | const | const _cast |
continue | default | delete | do |
double | dynamic _cast | else | enum |
except | explicit | extern | false |
finally | float | for | friend |
goto | if | inline | int |
long | mutable | namespace | new |
operator | private | protected | public |
register | reinterpret _cast | return | short |
signed | sizeof | static | static _cast |
struct | switch | template | this |
throw | true | try | type _info |
typedef | typeid | typename | union |
unsigned | using | virtual | void |
volatile | wchar_t | while |
命名空间
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作
用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字
污染,namespace关键字的出现就是针对这种问题的,std:c++标准库的命名空间。
在C语言中我们如果使用了同一个标识符定义了不同的函数或者是变量,会导致它们之间产生冲突,而C++为了解决这个问题,引入了命名空间的概念,不同命名空间的成员占有不同的内存空间,即使名称相同,但相互之间并不会受到影响。因此在C++中,库函数也是被定义在命名空间中的。
例如:C语言的头文件包含通常是 #include<xxx.h>
,包含后我们便可以直接使用库函数,而在C++中我们的头文件通常是: #include<xxx>
,并且无法直接使用库函数,必须要指定命名空间std
才能使用。
不过C++是兼容C几乎所以语法的,因此我们可以在C++中穿插C的代码,不过有一些混用是很容易出错的,要小心并且正确的使用。
命名空间定义
定义命名空间需要使用namespace关键字,后面跟上要定义的命名空间的名字,将命名空间成员定义在后面的{}内即可,类似于结构体和类的定义方式。
命名空间内可以定义变量,函数,类型,使用命名空间的类型定义出的变量不属于命名空间。
一般的命名空间定义方式
namespace sx
{
int a;
void swap(int& a, int& b)
{
cout << " namespace:sx " << endl;
int tmp = a;
a = b;
b = tmp;
}
struct Stu
{
char name[10];
int age;
};
}
命名空间的嵌套定义
namespace sx
{
int a;
void swap(int& a, int& b)
{
cout << " namespace:sx " << endl;
int tmp = a;
a = b;
b = tmp;
}
struct Stu
{
char name[10];
int age;
};
namespace psm
{
int b;
void print()
{
cout << "hello psm!" << endl;
}
}
}
同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中
namespace n1
{
int a;
void swap(int& a, int& b)
{
cout << "n1:swap" << endl;
}
}
namespace n2
{
int b;
}
namespace n1
{
int c;
void swap(int& a, int& b)
{
cout << "n1:swap" << endl;
}
}
像这样子去定义编译时会报错:
函数“void n1::swap(int &,int &)”已有主体
删除其中一个即可正常编译,由此可见编译时两个名字相同的命名空间会合并,如果有重复的定义则会报错。
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
命名空间的使用
定义在命名空间中的变量、类型以及函数我们是无法直接使用的,由于命名空间就定义了一个新的作用域,而程序中默认是只使用两个作用域的内容的:
- 全局作用域
- 局部作用域
并且根据局部优先原则会程序会先检索当前作用域的内容,如果没有我们需要的,再到全局域去检索,所以默认情况下我们所定义的命名空间的作用域的内容我们是无法直接访问的。
比如:
namespace sx
{
int a;
void swap(int& a, int& b)
{
cout << " namespace:sx " << endl;
int tmp = a;
a = b;
b = tmp;
}
struct Stu
{
char name[10];
int age;
};
}
int main()
{
cout << a << endl;//该语句编译出错,无法识别a
return 0;
}
报错:“a”: 未声明的标识符
命名空间的使用方式有三种:
- 加命名空间名称及作用域限定符
int main()
{
cout << sx::a << endl;//指定使用在sx这个命名空间中的a
return 0;
}
作用域限定符是临时的,因此每次使用时都需要加命名空间和作用域限定符(限定符限定的是成员的名称,因此限定符应紧挨着在成员名称的前面,例如:sx::Stu s
- 使用using将命名空间中成员引入至全局域
using sx::a;//指定地将sx中的a引入
int main()
{
cout << a << endl; //可以使用a
Stu s; //无法使用Stu类型
return 0;
}
这样只能使用指定引入的成员,并且引入时指定的应是成员的名称(变量名吗,函数名,类型名)。
- 使用using namespace 将命名空间中的成员引入至全局域
using namespace sx;
int main()
{
cout << a << endl;
Stu s;
return 0;
}
这种方法会将命名空间的所有成员一次性引入,可以直接访问其中所有的成员,平时我们可以这样使用,但是着违背了命名空间诞生的初衷,容易产生命名冲突的问题,因此在工程中通常是使用第一种或者第二种方法。
如何证明命名空间是被引入至全局域的呢?
int a = 1;
using namespace sx;
int main()
{
cout << a << endl;//“a”: 不明确的符号
return 0;
}
using namespace sx;
int main()
{
int a = 1;
cout << a << endl;
return 0;
}
第一个程序提示错误,而第二个程序正常运行。
引入至全局域后我们的程序即可在全局域中找到定义在命名空间sx
中的变量 a
,而我们本身又在全局域中定义了一个变量 a
,那么自然如果不指定是哪个域中的也就产生了歧义,使得a
变量名指代不明确。
可如果我们再次定义的a
变量是局部的,即使命名空间中的a
被引入至全局域,但并不会产生歧义,因为局部优先的原则,我们并不会去全局域中检索变量