命名空间
使用命名空间是要对标识符的名称进行本地初始化,避免命名冲突。
定义命名空间需要用到namespace关键字,后跟命名空间的名字,在{}内为命名空间的成员
//普通的命名空间
namespace N1{ //命名空间的名称为N1
//可定义变量也可以定义函数
int a = 10;
int add(int x, int y){
return x + y;
}
}
//嵌套的命名空间
namespace N2{
int a = 20;
int b = 30;
int add(int x, int y){
return x + y;
}
namespace N3{
int a = 10;
int sub(int x, int y){
return x - y;
}
}
}
//同一工程中允许存在多个相同名称的明明空间
//编译器会合成同一个命名空间
namespace N1{
//int a = 30; //错误,之前已经定义变量a
int mul(int x, int y){
return x * y;
}
}
命名空间通过作用域限定符::来使用
#include <iostream>
using namespace std;
namespace N{
int a = 10;
int b = 20;
int add(int x, int y){
return x + y;
}
}
int a = 50;
int main()
{
int a = 90;
cout<<a<<endl;
cout<<::a<<endl;
cout<<N::a<<endl;
return 0;
}
上面通过作用域限定符来使用命名空间,还可以通过关键字using将命名空间成员引用
using N::a;
int main()
{
cout<<a<<endl;
}
使用using namespace引入命名空间:
using namespace N;
int main()
{
cout<<a<<endl;
add(10, 30);
return 0;
}
缺省参数
缺省参数就是在声明或者定义函数时为函数的参数指定一个或多个默认值,在使用该函数时,如果没有指定的参数,就使用默认值
void test(int a = 10)
{
cout<<a<<endl;
}
int main()
{
test(); //没有传参使用默认值10
test(20); //传参使用指定参数20
}
缺省参数分为全缺省参数和半缺省参数
//全缺省参数
void test(int a = 10, int b = 20, int c = 30)
{
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;
}
//半缺省参数
void test(int a, int b = 20, int c = 30)
{
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;
}
半缺省参数的参数必须从左到右依次来给,不能出现间隔,并且缺省参数不能在定义和声明中同时出现(一般出现在声明中),缺省参数必须是全局变量或者常量
函数重载
函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数,类型,顺序)必须不同,函数重载通常是编译器在编译阶段根据实参确定的,常用来处理实现功能类似数据类型不同的问题。
int add(int x, int y)
{
return x + y;
}
double add(double x, double y)
{
return x + y;
}
long add(long x, long y)
{
return x + y;
}
int main()
{
add(1, 2);
add(2.0, 4.3);
return 0;
}
两个函数只有返回值不同,是不能形成重载的,根据重载的定义可以知道,只有形参列表不同时,才可以形成函数重载,另外,无参函数和全缺省函数尽量不要重载,会形成歧义,编译器无法确定该执行哪个函数。
那么C++底层是如何实现重载的呢,我们可以先来看一段简单的重载代码
#include <iostream>
using namespace std;
int add(int x, int y);
double add(double x, double y);
int main()
{
add(1, 2);
add(1.0, 2.0);
return 0;
}
在Linux环境下通过命令来让程序停止在汇编阶段
g++ -S test.cpp -o test.s
可以看到编译器在底层调用的不是add函数,而是_Z3addii和_Z3adddd两个函数,所以我们猜想编译器会在底层对重载函数重新进行修饰,被重新修饰后的名字中包含了:函数的名字以及参数类型。这就是为什么函数重载中几个同名函数要求其参数列表不同的原因。只要参数列表不同,编译器在编译时通过对函数名字进行重新修饰,将参数类型包含在最终的名字中,就可保证名字在底层的全局唯一性。C语言不支持函数重载的原因就是编译器不会去修饰函数名,在底层也还是用add这个单纯的函数名。
当然我们有时候需要在C++中用C的语法来编译某些函数,在这些函数之前加上extern "C"即可。