1.namespace关键词命名空间
namespace命名空间可以将标识符名称本地化,以避免命名冲突。每个命名空间都是相互隔离开来,我们需要使用时就可以指定访问某个命名空间的某个标识符。
使用方法1.加空间名称和作用域解析运算符::
#include<iostream>
namespace p
{
int a = 10;
}
namespace p1
{
int a = 20;
}
int main()
{
std::cout << p::a<<std::endl;
std::cout << p1::a;
return 0;
}
使用方法2:使用using将命名空间的某个值引入
这个代码中就将p中的a引入了全局中。
#include<iostream>
namespace p
{
int a = 10;
}
namespace p1
{
int a = 20;
}
using p::a;
int main()
{
/*std::cout << p::a<<std::endl;
std::cout << p1::a;*/
std::cout << a << std::endl;
return 0;
}
使用方法3:使用using namespace引入整个命名空间
#include<iostream>
namespace p
{
int a = 10;
}
namespace p1
{
int a = 20;
}
using namespace p;
int main()
{
/*std::cout << p::a<<std::endl;
std::cout << p1::a;*/
std::cout << a << std::endl;
return 0;
}
注:命名空间可以嵌套,当.cpp和.h中有名称相同的命名空间时,最终会合并成一个
2.输入输出流
std是c++标准库的命名空间名称,c++将标准库的定义都放在了std命名空间中
cout和cin就是std库中的输出输入流,当我们使用时首先要将<iostream>头文件引入;
<<是流插入运算符,>>是流提取运算符;
3.残缺参数
c++的函数声明和定时,允许函数的参数值确定一个缺省值;
具体分为全有缺省值和半有缺省值;半缺省参数必须从左往右依次给出,不能中断;
int Func1(int a = 10, int b = 20)
{
return a + b;
}//全缺省
int Func2(int a, int b = 20, int c = 10)
{
return a + b + c;
}//半缺省
4.函数重载
再c++中,允许函数名称相同,但是参数列表(形参数,形参类型,形参类型顺序)不同(与返回值无关)。用来处理功能类似,数据类型不同的问题;
int Add(int a, int b)
{
return a + b;
}
int Add(int a)
{
return a + a;
}
int Add(float a, int b)
{
return a + b;
}
int Add(int b, float a)
{
return a + b;
}
上述的函数都是合法的,并没有报错。
4.1 c++支持函数重载的原因(名字修饰)
无论是c还是c++,要生成一个可执行程序,都需要经过编译(处理-i-编译-s汇编-o)和链接的过程。
假设函数在a.c定义,在b.c中调用。在a.c中定义了 void add(int i,double j),int add (double j ,int i)当b.c中调用 void add(int i,double j)。
在编译时a.c就会被编译生成汇编代码,每个.o文件都会有符号表,其中就包含了函数的名称和地址。在Linux下,例如 void add(int i,double j)这个函数在汇编代码中的名称就为_Z3addid,int add (double j ,int i)在汇编代码中的名称就为_Z3adddi.(可见汇编中函数名称与返回值无关)当链接器看见b.o文件在调用_Z3addid时没有函数地址,就会在a.o的符号表中寻找,然后链接到一起,可见这两种函数并不冲突。
5.extern"C"
当c与c++程序都想调用一个用c++实现的库时,由于c++中的名字修饰,在链接时c就链接不到c++
实现的库函数,我们就可以在函数声明中加入extern“C”,让c++库和c++程序使用c语言的命名规则对这个函数进行访问。
6.引用
引用就是给函数起了个别名,具体操作如下
int main()
{
int a = 10;
int& b = a;
return 0;
}
实际上a和b都指向同一块空间。
引用时的权限只能给小,不能给大
int main()
{
const int a = 10;
// int& b = a; 这条代码就是错误的,因为a只能只读,而这里的b既能读也能写
const int& b = a; // 正确
int c = 10;
const int c1 = c; /// 正确
return 0;
}
特殊的
int main()
{
// const int a = 10;
// // int& b = a; 这条代码就是错误的,因为a只能只读,而这里的b既能读也能写
// const int& b = a; // 正确
// int c = 10;
// const int c1 = c; /// 正确
int c = 10;
const double c1 = c;
return 0;
}
这个代码也是真确的,为啥呢?
调试时我们观察到,此时c1与c已经不指向同一块空间了,这里就牵扯到类型转换时,例如一个int值转化为double值时,实际上会先创建一个double的临时变量,int转为double的值先储存在临时变量中,再将这个临时空间的值给double。这里也是类似的道理 ,临时变量具有常性,这里的c1已经不是引用的c了,而是那个临时变量。
那么这里就可以理解为什么不同类型的不能引用了,实际上是临时变量具有常性,而例如double& c1 = c;这里的c1就是既能读也能写,权限扩大了,当然就不能引用了。