002 C++基础篇
前言
大家好,本文将会向您介绍C++的命名空间、缺省/半缺省参数、函数重载相关知识
命名空间
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存
在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,
以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}
中即为命名空间的成员。
我们先看一个程序
#include <stdio.h>
#include <stdlib.h>
int rand = 0;
int main()
{
printf("%d", rand);
return 0;
}
error: “rand”: 重定义;以前的定义是“函数”
那是因为头文件<stdlib.h>中定义了一些标准库函数,其中包括rand()函数用于生成随机数。在全局作用域中,全局变量名rand与<stdlib.h>中定义的rand函数名冲突
默认情况下:变量只会在全局中查找,而不会到命名空间中查找。
在一个项目中,时常会遇到这种命名冲突的情况,如果不使用命名空间,就会导致其中的一个人需要去改一下变量名,因此我们使用命名空间来避免这种情况。
ps:namespace(根据自身情况命名)
{
//定义变量、函数、类型
}
域作用限定符
域作用限定符使用双冒号"::"来表示,它的一般形式是"命名空间::变量/函数/类
使用命名空间有三种格式
1、命名空间+作用域限定符 as :Fan::cat
2、部分展开——使用using将命名空间某个成员引入 as : using Fan::dog;
3、全展开——using namespace (…) as : using namespace Fan
ps:建议在代码中谨慎使用全展开命名空间。如果存在多个命名空间存在同名的标识符也会造成命名冲突等情况。最好的做法是只引入需要的标识符,以避免命名冲突、不可预测的行为和提高代码的可读性。
//命名空间中可以定义变量、函数、类型
namespace Fan
{
int cat = 1;
int dog = 2;
int Add(int cat, int dot)
{
int ret = cat + dog;
return ret;
}
struct Node
{
struct Node* node;
int val = 0;
};
}
using Fan::dog; //使用using将命名空间某个成员引入
int main()
{
//printf("%d\n", cat); //error:未定义标识符
printf("%d\n", Fan::cat); //命名空间+作用域限定符
printf("%d\n", Fan::Add(Fan::cat,Fan::dog)); //命名空间+作用域限定符
printf("%d\n", dog);
}
//全展开命名空间
using namespace Fan;
int main()
{
printf("%d\n", cat);
printf("%d\n", Add(cat, dog));
printf("%d\n", dog);
}
缺省/半缺省参数
缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实
参则采用该形参的缺省值,否则使用指定的实参。
//缺省参数
void func1(int a = -1)
{
cout << a << endl;
}
int main()
{
func1();
func1(1);
return 0;
}
我们可以观察到,第一个值为-1为默认值,第二个为我们指定的参数1
半缺省参数
//半缺省参数
void func2(int a, int b = 10, int c = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
int main()
{
func2(0);
func2(1,2,3);
return 0;
}
注意:半缺省参数需要从右往左来给,不能间隔给
调用函数的时候,可以有选择地提供参数覆盖
我们可以观察到。第一次调用我们仅传了一个参数 0 ,而这个参数将会从左向右覆盖
函数重载
C++的函数重载体现在:同名函数的参数类型不同、参数顺序不同、参数个数不同
//以此为基与下面的多个func比较
void func(int i, double d)
{
cout << "void func(int i,double d)" << endl;
}
//参数类型顺序不同
void func(double d, int i)
{
cout << "void func(double d,int i)" << endl;
}
//参数个数不同
void func(int i)
{
cout << "void func(int i)" << endl;
}
//参数个数不同
void func()
{
cout << "void func()" << endl;
}
//参数类型不同
void func(char i, char d)
{
cout << "void func(char i,char d)" << endl;
}
int main()
{
func('a','b');
func(1);
func(1, 1.1);
func(1.1, 1);
func();
return 0;
}
根据我们传入的参数不同,会有不同的调用结果,我们来看看调用结果
函数名修饰规则
C语言没有函数重载,而C++却有,原因是C语言没有函数名修饰规则,单纯以函数名调用,这导致符号表中存储的函数名会乱,如有同名函数,从而不知调用哪一个。而C++有,函数名修饰规则因编译器而异(本文基于VS2019)
但通常根据:函数名、参数类型、参数个数。注意返回类型不会影响函数名修饰规则()
将函数定义屏蔽掉我们来看看
观察到
void __cdecl func(int,double)" (?func@@YAXHN@Z)
void __cdecl func(double,int)" (?func@@YAXNH@Z)
void __cdecl func(int)" (?func@@YAXH@Z)
void __cdecl func(void)" (?func@@YAXXZ)
void __cdecl func(char,char)" (?func@@YAXDD@Z)
其中的差异取决于编译器的函数名修饰规则不同
小结
文本是C++入门篇,建议初学者将文中代码能够打一下然后运行重在理解。如果本文有疏漏或错误的地方还请您能指出。祝您天天开心啦!