* 命名空间
需要使用到namespace 关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
//1. 普通的命名空间
namespace N1 // N1为命名空间的名称
{
// 命名空间中的内容,既可以定义变量,也可以定义函数
int a;
int Add(int left, int right)
{
return left + right;
}
}
//2. 命名空间可以嵌套
namespace N2
{
int a;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N3
{
int c;
int d;
int Sub(int left, int right)
{
return left - right;
}
}
}
//3. 同一个工程中允许存在多个相同名称的命名空间
// 编译器最后会合成同一个命名空间中。
namespace N1
{
int Mul(int left, int right)
{
return left * right;
}
}
注意:
一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
命名空间的三种使用方法:
//全缺省 默认的调用约定(_cdecl):从右向左依次传,左边最先接受
void Function(int a=10,int b=20,int c=30)
{
printf("a=%d\n",a);
printf("b=%d\n",b);
printf("c=%d\n",c);
}
int main()
{
FunTest(); //10 20 30
Funtest(1,2,3); //1 2 3
Function(1); //1 20 30
Function(1,2); //1 2 30
}
//半缺省
void Function(int a=10,int b=20,int c) //不可以
void Function(int a=10,int b,int c) //不可以
void Function(int a=10,int b,int c=30) //不可以
注意:缺省值只能从右向左依次给,也不能跳着给
void Function(int a,int b=20,int c=30)
{
printf("a=%d\n",a);
printf("b=%d\n",b);
printf("c=%d\n",c);
}
注意:
1.带缺省的参数必须必须放在参数列表的最后面
2.缺省参数不能同时在函数声明和定义中出现,只能二者则其一
3.缺省值必须是常量或者全局变量
4.C语言不支持
5.缺省参数放在声明位置比较好
- 重载函数
一词多义——-多义词——–重载
int Add(int a,int b)
{
return a+b;
}
double Add(double a,double b)
{
return a+b;
}
char Add(char a,char b)
{
return a+b;
}
int main()
{
Add(1,2);
Add(1.0,2.0);
Add('1','2'); //49+50=99----->'c'
}
必须在同一个作用域,函数名相同,参数列表不一样(参数个数不一样,参数类型不一样,参数类型的次序不同)
仅仅是返回值类型不同,是不能构成函数重载的
int Funtest(int a)
{}
//参数个数不一样
int Funtest(int a,int b)
{}
//参数类型不一样
int Funtest(char a)
{}
//参数类型的次序不一样
int Funtest(int a,char b)
{}
int Funtest(char a,int b)
{}
// 仅仅是返回值类型不同,是不能构成函数重载的
void Funtest(int a)
{}
为什么C语言不支持?
预处理
编译
汇编
链接
VS这个编译器的修饰规则:int --- H char ----- D
int Add(int a,int b); ----------------- ?Add@@YAHHH@Z
char Add(int a,int b); ------------------- ?Add@@YADHH@Z
char Add(int a,char );------------------- ?Add@@YADHD@Z
C语言和C++在底层的处理方式不一样:
1>C++的底层把函数换了一个名字存着
2>C语言对于函数的修饰只是在函数名前面加了一个_,比如 _Add,即使函数列表不一样,他们都是 _Add
如何把C++按照C的风格来编译
在函数体前面加上 extern “C”
- 引用
C语言里传值和传参的优缺点:
- 传值:
缺点:不能通过修改来该变外部实
优点:函数的副作用不会影响外部实参 - 传地址:
缺点:指针不安全,
优点:节省空间,效率高,改变参数可以修改外部实参
- 传值:
C++可以把C语言里传值和传地址的优点结合起来:
函数改变形参就可以改变实参。所以就有了引用。
* 引用概念:
引用不是定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
注意:引用类型必须和引用实体是同种类型的。
- 引用特性:
1.引用在定义时必须初始化
2.一个变量可以有多个引用
3.引用一旦引用一个实体,再不能引用其他实体
void TestConstRef()
{
const int a = 10;
//int& ra = a; // 该语句编译时会出错,a为常量
const int& ra = a;
// int& b = 10; // 该语句编译时会出错,b为常量
const int& b = 10;
double d = 12.34;
//int& rd = d; // 该语句编译时会出错,类型不同
const int& rd = d;
}
- 数组的引用
void PrintArray(int (&array)[10])
{
for(size_t i = 0; i < 10; ++i)
cout<<array[i]<<" ";
cout<<endl;
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,0};
PrintArray(array);
return 0;
}
引用的使用
- 作形参
void Swap(int& left,int& right)
{
int temp = left;
left = right;
right = temp;
}
* 作返回值
int& Test(int& a)
{
a += 10;
return a;
}
注意:不要返回栈空间的地址,看下面这个例子:
int& Add(int a,int b)
{
int c = a+b;
return c;
}
int main()
{
int& ret = Add(10,20);
Add(100,200);
cout<<"Add(10,20) is :"<<ret<<endl;
return 0;
}
引用和指针的区别:
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共同用一块空间,其实在底层实现上实际是有空间的,因为引用是按指针的方式来实现的。
引用和指针的不同:
- 引用在定义时必须初始化,指针没有要求
- 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
- 没有NULL引用,但有NULL指针
- 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
- 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
- 有多级指针,但是没有多级引用
- 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
- 引用比指针使用起来相对更安全
内联函数
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。
特性
1.inline是一种以空间换时间的做法,省去调用函数的开销,所以代码很长或者有循环/递归的函数不适宜使用作为内联函数
2.inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等,编译器优化时会忽略掉内联。
宏:优点:
1.增强代码的复用性
2.提高性能
3.可以传类型缺点:
1.不方便调试宏(因为在预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易出错
3.没有类型安全的检查C++有哪些技术替换宏
- 常量定义 换用const
- 函数定义 换用内联函数
- 类型重定义 换用typedef