1.命名空间
关键字:namespace
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作 用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字
污染,namespace关键字的出现就是针对这种问题的。
命名空间的定义
定义命名空间,需要使用到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;
}
}
命名空间的使用
命名空间的使用有三种方式:
加命名空间名称及作用域限定符
使用using将命名空间中成员引入
使用using namespace
//1.使用命名空间名称及作用域限定符
int main()
{
printf("%d\n", N::a);
return 0;
}
//2.使用using将命名空间中成员引入
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
//3.使用using namespace
using namespce N;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
Add(10, 20);
return 0;
}
在C++中我们开头总是写using namespace std; 很多人压根不知道这句话的意思,这里的std就是命名空间,当然这句话的意思就是使用标准命名空间
2.函数缺省
缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。
缺省参数分类:
全缺省参数
半缺省参数
//1.全缺省参数
void TestFunc(int a = 10, int b = 20, int c = 30)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
//2.半缺省参数
void TestFunc(int a, int b = 10, int c = 20)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
注意:
- 半缺省参数必须从右往左依次来给出,不能间隔着给
- 缺省参数不能在函数声明和定义中同时出现
- 缺省值必须是常量或者全局变量
- C语言不支持(编译器不支持)
3 .函数重载
函数重载:即在C++中容许有同名的函数 函数重载的条件:函数的参数类型不同,返回值不同 注:函数的返回值不能构成函数重载的条件
#include<iostream>
using namespace std;
void Print(int a)
{
cout << a << endl;
}
void Print(double a)
{
cout << a << endl;
}
int main()
{
Print(1.0);
Print(1);
return 0;
}
如上述例子所述,我们要实现两个自定义打印函数,一个打印整数,一个打印浮点数,两个函数列表的参数类型不同
而函数名却相同,但是我们在编译时却不会报错,这就是函数重载,让我们实现了打印两个不同类型打印函数
而在C语言中我们就要起两个函数名来实现这件事,如Print_int,Print_double
那么为什么会出现函数重载这件事呢,这就要从编译链接的过程开始说起:
1.预处理:头文件的展开+宏替换+去掉注释+条件编译
2.编译:检查语法,将代码转化成汇编代码
3.汇编:汇编代码转化为二进制的机器码
4.链接:将所有文件连接在一起,生成可执行程序 而C++在编译过程中有函数名修饰规则:函数的返回值+函数名+函数参数类型,这样每个函数就能够进行独立识别,既不会产生命名冲突,如下所示:
#include<iostream>
void print(int a)
{
cout << a << endl;
}
void print(string str)
{
cout << str << endl;
}
using namespace std;
int main()
{
print(1);
print("hello world");
}
将上述代码在Linux下利用g++编译之后,我们会产生下述结果:
这里我们会发现void print(int a)在这里变成了_Z5printi
而void print(string str)在这里变成了_Z5printSs
我们来对比一下:
从void print(inta)—>_Z5printi;
而void printf(string str)—>_Z5printSs;
前面_Z5我们也许不认识,但是看到print我们应该能够联想到这是我们定义的函数名,那么后面的i我们也就可以去联想到知识函数的参数类型,i代表int,Ss代表string,那么我们就可以大胆的猜测_Z5就是前面的函数的返回值类型,这样每一个函数在编译之后:就会形成:
函数返回值+函数名+参数列表类型
这将成为为函数唯一修饰,这样看似两个相同的函数就会被特定的区别开来,也就出现了函数重载现象
而在C语言中,我们将下面代码在Linux gcc下编译之后:
#include<iostream>
using namespace std;
int Ad(int a, int b)
{
return a + b;
}
void func(int a, double b, int* p)
{
}
int main()
{
return 0;
}
并没有出现像上面C++中那样有函数名修饰规则,而是直接就写了函数名,这样要是出现两个相同的函数名他就无法进行区分,则会报错,这也就解释了为什么C++支持函数重载,而C语言不支持函数重载,总而言之就是二者的函数名修饰规则不同
2.引用
简单来说就是给一个变量起别名 引用不是重新写一个变量,而是给一个变量起别名,他和他引用的变量共同访问一块内存空间
基本语法:数据类型 &别名 = 原名
例如 int a=10;
int &b=a;
如上图所示,我们给变量a起别名为b,此时变量a和b就能共同访问这块内存空间,此时我们改变b的值为100,我们会发现a的值也会变为100,这就是最基础的引用
.引用的注意事项: 引用必须初始化 引用在初始化后不可以改变
引用的作用
1.引用做函数参数
作用:函数传参时,可以利用引用的技术让形参修饰实参
实例:
#include<iostream>
using namespace std;
//交换函数
//1.址传递
void swap1(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "swap1 a=" << a << endl;
cout << "swap2 b=" << b << endl;
}
//2.地址传递
void swap2(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//3.引用传递
void swap3(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int a = 10;
int b = 20;
//swap1(a, b);//值传递形参不会改变实参
//swap2(&a, &b);//地址传递形参会改变实参
swap3(a, b);//引用传递形参也会修饰实参
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
总结:引用的效果和地址传递效果是一样的,引用语法更加清楚简单
2.引用做函数返回值
作用:引用是可以做函数返回值存在的
注意:不要返回局部变量引用
实例:
#include<iostream>
using namespace std;
//引用做函数返回值
//1.不要返回局部变量的引用
int& test01()
{
int a = 10;//局部变量在栈区中
return a;
}
//2.函数的调用可以作为左值
int& test02()
{
static int a = 10;//全局变量程序运行完后由系统自动释放
return a;
}
int main()
{
int &ret=test01();
cout << ret << endl;//第一次正确,编译器做了保留,
cout << ret << endl;//第二次错误,因为a的内存已经释放
int& ref = test02();
cout << "ref=" << ref << endl;
cout << "ref=" << ref << endl;
test02() = 1000;///如果函数返回值是引用,这个函数调用可以作为左值
cout << "ref=" << ref << endl;
system("pause");
return 0;
}
引用的本质
本质:引用的本质在c++内部实现是一个常量指针
int&a=b==>int* contst a=&b;
指针指向不可以修改,但是其值可以修改
PS:引用一旦初始化就不可以发生变化
#include<iostream>
using namespace std;
void test(int& a)
{
a = 100;
}
int main()
{
int a = 10;
int& b = a;//相当于int* const b=&a;
b = 20;//相当于*b=20
cout << "a=" << a<<endl;
cout << "b=" << b << endl;
test(a);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
以上就是本篇文章所有内容,希望各位看官能够喜欢,如果有错误的地方,还请多多斧正,感谢大家支持
转载:https://blog.csdn.net/weixin_51476766/article/details/117042707