🐶博主主页: @ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列: 线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux
🔥座右铭:"不要等到什么都没有了,才下定决心去做"
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
命名空间
在 C++ 中,命名空间(Namespace)是一种用于组织代码和避免命名冲突的机制。通过命名空间,可以将一系列的标识符(如变量、函数、类等)封装在一个命名空间中,从而在不同的作用域中避免名称冲突。
命名空间的语法形式如下:
cppnamespace namespace_name { // 声明或定义一些变量、函数、类等 }
命名空间的使用
cppnamespace E { int a = 10; int b = 20; int Add(int left, int right) { return left + right; } int Sub(int left, int right) { return left - right; } } 加命名空间名称及作用域限定符 int main() { printf("%d\n",E::a); return 0; } 使用using将命名空间中成员引入 using E::b; int main() { printf("%d\n", E::a); printf("%d\n", b); return 0; } 使用using namespace 命名空间名称引入 using namespace E; int main() { printf("%d\n", E::a); printf("%d\n", b); Sub(10, 20); return 0; }
using namespace std;
std 这个空间,包含一些输入输出,例如 cout,cin对象
C++的输入输出
在 C++ 中,输入输出通常使用
iostream
库来实现。主要的输入输出对象是cin
和cout
。1.使用cout标准输出(控制台)和cin标准输入(键盘)时,必须包含< iostream >头文件以及std标准命名空间。
注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用<iostream>+std的方式。
- 使用C++输入输出更方便,不需增加数据格式控制,比如:整形--%d,字符---%c
cppusing namespace std; int main() { char s[10]; cin>>s; cout<<s<<endl; cout<<'A'<<endl; cout<<65<<endl; return 0; }
缺省参数(默认参数)
在 C++ 中,函数的默认参数(也称为缺省参数)允许在函数声明中为参数提供默认值。这意味着在调用函数时,如果没有为相应的参数提供值,则会使用参数的默认值。默认参数在函数声明中指定,而不是在函数定义中。
事例
cpp#include<iostream> using namespace std; void test(int a=1) { cout<<a<<endl; } int main() { test();//没有传参时,使用参数的默认值 test(0);//传参时,使用指定实参 return 0; }
需要注意的是,对于函数的多个参数,只能在参数列表的末尾提供默认参数,不能在中间部分提供。例如:
cpp// 错误示例:不能在非末尾参数提供默认参数 void example(int a = 1, int b, int c = 3);
正确的写法是将默认参数放在参数列表的末尾:
cpp// 正确示例:将默认参数放在参数列表的末尾 void example(int a, int b, int c = 3);
全缺省参数
每个参数都有默认值
cppvoid test(int a=1,int b=2,int c=3) { cout<<a<<endl; cout<<b<<endl; cout<<c<<endl; }
半缺省参数(部分缺省)
部分参数有默认值
cppvoid test(int a,int b,int c=3) { cout<<a<<endl; cout<<b<<endl; cout<<c<<endl; }
半缺省参数必须从右向左依次给出,不能间隔
cppvoid test(int a=0,int b,int c=3)//错误的 void test(int a,int b=2,int c=3)//正确的
不允许声明和定义同时给缺省参数
cpp//a.h void test(int a = 10); // a.c void test(int a = 20) {}
注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值
函数重载
自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。
比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是"谁也赢不了!",后者是"谁也赢不了!"
在 Linux 中,函数重载与其他 C++ 编译环境中的函数重载方式相同。函数重载是指在同一个作用域内定义多个具有相同名称但参数列表不同的函数。在调用这些函数时,编译器会根据参数列表的不同来确定调用哪个函数。
事例
cppusing namespace std; int test(int a,int b) { return a+b; } double test(double a,double b) { return a+b; } long test(long a,long b) { return a+b; } int main() { cout<<test(1,2); cout<<test(1.0,2.0); cout<<test(1L,2L); return 0; }
函数重载的特点包括:
1)函数名称相同。
2)参数列表不同(包括参数类型、个数、顺序等)。
3)返回类型可以相同也可以不同,但不能仅仅通过返回类型来进行函数
为什么C++支持函数重载,而C语言不支持函数重载呢?
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
test.cpp
预处理 头文件展开/宏替换/去掉注释/条件编译
test.i
编译 检查语法,生成汇编代码(指令级代码)
test.s
汇编 将汇编代码生成二进制机器码
test.o
链接 合并链接,生成可执行程序
实际我们的项目通常是由多个头文件和多个源文件构成,而通过我们C语言阶段学习的编译链接,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么怎么办呢?
所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。那么链接时,面对Add函数,连接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。
Linux下gcc的修饰规则简单易懂,下面我们使用了gcc演示了这个修饰后的名字。
通过下面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】。
在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变,采用C++编译器编译后结果
结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中总结:通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。另外我们也理解了,为什么函数重载要求参数不同!而跟返回值没关系
C++函数支持重载详细介绍
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸