> 文档中心 > 【C++登山之路之语法高山 1】—— 命名空间+缺省参数+函数重载(万字详解,图片演示,结构原理)

【C++登山之路之语法高山 1】—— 命名空间+缺省参数+函数重载(万字详解,图片演示,结构原理)

目录

🌏命名空间

🌙命名空间定义

🌙命名空间的使用

🌏缺省参数

🌏函数重载

🌙函数重载底层原理

        🌙C和C++的相互调用

即使前方的路依旧艰险且看不清方向,也不要停止你的脚步~


        ps:Pexels 上的 Creative Vix 拍摄的图片   

🌏命名空间

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

🌙命名空间定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{ }即可,{ }中即为命名空间的成员。

一个命名空间就定义了一个新的作用域(从而区分内外即使是相同的成员名字),命名空间中的所有内容都局限于该命名空间中

举个例子🌰

namespace A{int a;//可以是变量,变量可以赋值int b = 10;int Add(int a, int b);//可以函数声明或定义int Add(int a, int b){return a + b;}}

同时命名空间的使用还有很多规则❗❗❗

(1)嵌套使用

namespace A{int a;int b = 10;int Add(int a, int b);int Add(int a, int b){return a + b;}namespace B     //命名空间还可以嵌套使用,甚至嵌套的名字也可以相同(但这样无法区分){int c;      //同名嵌套无法合并int d;int Sub(int left, int right){return left - right;}}}//namespace A

(2)同名命名空间会被合并

namespace N1{    int Mul(int left, int right)    { return left * right;    }}namespace N1  //同一层的命名空间会被合并{int a;char b;}

🌙命名空间的使用

(1)使用空间名称和作用域限定符 : :

int main(){    printf("%d\n", N1::a); //其中::左边为空间作用域,右边为成员    return 0;      //左边为空时表全局域,如 ::a}

(2)使用using将命名空间中成员引入

using N1::b;     //使用指定区域的指定成员,因不是直接使用命名空间int main()      //故不需要加namespace{    printf("%d\n", N::a);    printf("%d\n", b);    return 0;}

(3)使用using namespace 命名空间名称引入

using namespce N1;int main(){    printf("%d\n", N::a);    //引入命名空间也可单独指定成员    printf("%d\n", b);    Add(10, 20);    return 0;}

说明❗❗❗

头文件以及std标准命名空间。std标准命名空间包含在头文件中

早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持格式,后续编译器已不支持,因此推荐使用+std的方式。


🌏缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。

举个例子🌰

void TestFunc(int a = 0)//函数调用是默认的形参{    cout<<a<<endl;}int main(){    TestFunc(); // 没有传参时,使用参数的默认值    TestFunc(10); // 传参时,使用指定的实参}

分类:全缺省 / 半缺省

全缺省:所有参数都缺省👇

半缺省:部分参数缺省👇

 半缺省注意事项❗❗:半缺省参数必须从右往左依次来给出(如上图),不能间隔着给,不然指派不明。

其他注意事项

(1)缺省参数不能在函数声明和定义中同时出现。即缺省参数不能重定义。

举个例子🌰

//a.h     两个不同文件若是有歧义,编译器无法识别void TestFunc(int a = 10);// a.c(定义)void TestFunc(int a = 20){}

需要注意的是:一般缺省参数在不同文件中是写在声明中的。这样方可保证其他文件编译期间不出问题。同一文件除外,但也还是不能同时出现在声明和定义中

(2)缺省值必须是常量或者全局变量。

(3)C语言不支持(编译器不支持)


🌏函数重载

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。

举个例子🌰

很好❗❗

其实在某种程度上函数重载也就解释完了

那我们来看看下面两个问题👇

这个函数构成函数重载吗❓

short Add(short left, short right){return left+right;}int Add(short left, short right){return left+right;}

这个呢❓

void TestFunc(int a = 10){cout<<"void TestFunc(int)"<<endl;}void TestFunc(int a){cout<<"void TestFunc(int)"<<endl;}

答案:不是的

所以对于我们来说,只知道什么是重载是完全不够的,作为一名未来的C++大佬,我们还要知道C++为什么支持重载,C语言为什么不支持重载,以及重载的原理是什么,C和C++能否相互编译?

🌙函数重载底层原理

知识回顾

C和C++会经过编译i链接最终转换称为机器语言,重载主要是链接问题,但是也离不开编译预处理。

对详细编译链接内容可以通过下面文章了解👇(188条消息) C语言《翻译环境和执行环境(预处理文件的生成)》_苏某的橡皮擦的博客-CSDN博客

预处理:头文件的引用,条件编译,宏替换,删除注释等等。

编译:检查语法,转换成汇编代码。

汇编:形成符号表(包含函数名和函数符号地址的映射),转为机器代码。

链接:合并段表,符号表的重定位(得出函数地址)

正文

在Linux下利用objdump -S命令即可查看符号标识👇

这是C++的(指针就用P+类型)

规则:_Z+函数名长度+函数名+类型

 这是C语言的

结论❗❗

 由此我们可以得知C和C++编译期间的函数符号命名规则是不一样的,C语言符号表中函数名单纯是存储了函数的名称,而C++连同类型及顺序都会存储,所以就回答了我们前面的几个问题,以及为什么是同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同了。

需要注意的是:

C++函数名的标识没有包括返回值的,故单单是返回值不同也是无法构成函数重载的。

🌙C和C++的相互调用

C和C++编译期间的函数符号名的规则不同 (重载)也就导致C和C++之间的文件无法直接调用。

你说直接改后缀名编译不久可以了吗?——但是并不是所有文件你都能直接操作,可能为静态库或者动态库等。

extern "C"(C++调用C)

有时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern "C",意思是告诉编译器,将该函数按照C语言规则来编译。比如:tcmalloc是google用C++实现的一个项目,他提供tcmallc()和tcfree两个接口来使用,但如果是C项目就没办法使用,那么他就使用extern “C”来解决。

//extern "C" int Add(int left, int right);//把需要的函数转换为C语言extern "C"     //或者直接包文件{    #include "../../" //相对路径头文件,..表示返回上一层}int main(){    Add(1,2);    return 0;}//或者直接括起来

注意❗❗:

extern "C"是C++的语法,C语言没有extern引用C++的说法

C调用C++

由于C++是包含C的,故改变也是在C++文件中改;

实现步骤

以c++编写的栈静态库去实现C语言文件中的题目

以下以两个文件进行操作test.c    stackCPP.lib(c++静态库)

⭐利用条件编译区分C和C++,改动依然在C++文件中

 ⭐或者这样(两个方式是一样的)

 然后链接静态库即可完成调用(只需引用相对路径的头文件,以及链接器附加依赖项和路径即可),详细的库连接就不在这列举说明了。


即使前方的路依旧艰险,看不清方向也不要停止你的脚步~

文章到这里就结束了(~ ̄▽ ̄)~,如果喜欢本文的话不妨三连。有问题的话可以评论区留言哦

点赞✔        收藏✔        关注✔

        ps: Pexels 上的 Tim Gouw 拍摄的图片