c++基础及其STL|c++基础篇——(一)c++快速入门(上)

写在前面
非常感谢各位小伙伴的支持!从c语言进阶和数据结构初阶系列,我们对c语言和数据结构的部分知识已经有了一定的了解。今天,我们将进入一个全新的系列c++系列!
另外,一些高级数据结构(图,哈希,红黑等)也在c++系列中,敬请期待!
还有STL源码系列!敬请期待!
c++基础及其STL|c++基础篇——(一)c++快速入门(上)
文章图片

作者介绍:

关于作者:东条希尔薇,一名喜欢编程的在校大学生
主攻方向:c++和linux
码云主页点我
本系列仓库直通车
作者CSDN主页地址

关于c++
c++发明出来,是用来弥补c语言的不足,大部分语法和特性是与c语言兼容的,所以在本系列我们只讲与c语言没有的特性

目录
  • 命名空间
    • 命名空间的定义
    • 命名空间的使用
    • 命名空间的使用场景
  • 用c++来向世界问好!
  • 缺省参数
    • 定义
    • 缺省参数的一些注意事项
  • 函数重载
    • 定义
    • 函数重载底层原理

命名空间 为什么会有命名空间?
例如我们有以下的使用场景:
我们一定要定义一个叫rand的变量:
int rand=0;

这种单独定义是没有问题的,但是我们如果要这么使用呢?
#includeint rand=0;

这种场景就报错了,因为我们的stdlib中也有rand函数!与我们的命名发生了冲突!
那么,我们为了解决命名冲突的问题,我们引入了命名空间,将一些全局变量,函数等进行封装,可以有效的将全局变量隔离,防止命名的污染。
一个命名空间就相当于定义了一个新的作用域,命名空间中的所有内容都局限于命名空间中,成员变量属于全局变量。
命名空间中可以定义变量,函数,甚至是结构体。
命名空间的定义
namespace N1 { int rand=0; }

使用通式:
namespace name { //memmber; }

请注意:命名空间内的变量只能允许声明和初始化,而不能赋值!
namespace N { int a; //ok int b=10; //ok b=20; //no }

命名空间的使用 在成员变量前声明命名空间
我们使用**作用域限定符(::)**来使用
使用方法:
N1::rand=2; //修改N1中的rand变量

用using展开部分变量
我们在一个命名空间中如果有多个变量
namespace N2 { int a=0; int b=0; }

我们不想在每次使用前都加限定符,而又想多次使用a变量
我们可以在代码最前面用using展开
using N2::a;

全部展开
将命名空间中的变量全部展开
用using namespace空间名来全部展开
using namespace N2;

但是这种方法要慎用:因为全部展开了后,隔离将会失效,就相当于没有隔离
命名空间的使用场景
  1. 你自定义的变量因为某种特殊原因,必须与库函数中的函数名重合
  2. 在公司的大型合作项目中,通常都是一个人完成某个代码片段,而在合作的过程中,难免会遇到变量名相同的问题,所以为了解决这个问题,通常一个人写的代码中使用的变量要使用命名空间来隔离
用c++来向世界问好! 我们初学一门语言,输出hello world是必不可少的
#include using namespace std; int main() { cout<<"hello world!"<

对以上程序的几点解释:
首先是iostream头文件,是标准输入/输出流文件,可以支持使用cout和cin等函数,替换printf和scnaf
其次是using namespace std,就是上篇文章我们讲到的命名空间,这个命名空间包含了c++所有的函数的声明
还有就是c++特有的输入输出,cout,cin
  • 其中<<是流插入符号,可以将所有你需要输出的变量或者字符串流入到cout中,让cout负责输出
  • 或者是可以通过cin,将你输入的值流入到某变量中。
  • endl与"\n"(换行符)等价
使用示例:
int a=10; float b=1.1; double c=0.0; cin>>c; cout<

使用cout输出更方便,不需要像printf一样的需要控制数据格式:%d,%f等
c++基础及其STL|c++基础篇——(一)c++快速入门(上)
文章图片

缺省参数 定义 缺省参数,是声明或定义函数时,为函数的参数指定一个默认值,例如
int Fun(int a=0)//这里为a指定了一个默认值0 { return a+1; }

我们以下两种调用都是有意义的:
Fun(); //没有指定参数,使用默认值 Fun(10); //指定了参数就用指定的参数值

缺省参数主要应用与一些我们有时候可能不太清楚参数该传什么值的情况,这时候我们就可以直接先传一个默认值进去。
缺省参数的一些注意事项 全缺省和半缺省
  • 全缺省就是为函数的所有参数都设置一个默认值,例如
int Fun(int a=1,int b=2,int c=3);

我们以下的调用都是有意义的:
Fun(); Fun(1); Fun(1,2); Fun(1,2,3);

传进去的实参是从左向右传的,而且必须连续
但是这种调用方法是不允许的:
Fun(,2,)//错误,不连续的传参

  • 半缺省是将参数部分初始化,例如
int Fun(int a,int b=10,int c=20);

注意:
  • 半缺省参数只能从右向左依次给出,而且必须连续,以下的场景是不行的
int Fun(int a,int b=20,int c); //不连续 int Fun(int a=10,int b,int c)//不是从右向左

  • 缺省参数不能在声明和定义中同时出现,只能任选一个来设置默认值
  • 缺省参数的默认值不能是变量
函数重载 定义
冷知识:重载在中文中的意思是一词多义
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的,形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题
举例说明:
int Add(int left, int right) { return left+right; } double Add(double left, double right) { return left+right; } long Add(long left, long right) { return left+right; }//这些函数满足参数类型不同的函数重载int F1(); int F2(int a); //满足参数个数不同int Sub(int a1,int b1); int Sub(int b1,int a1)//满足参数顺序不同

但这种情况不能构成重载
short Add(short left, short right) { return left+right; } int Add(short left, short right) { return left+right; }

为什么?
因为它们的参数相同,返回值不同不满足构成函数重载的条件!
函数重载底层原理 为什么c++支持函数重载而c语言却不支持呢?
我们知道,c++程序运行,需要经过以下几个阶段:预处理,编译,汇编,链接
而这里的重点在链接阶段,
通过我们C语言阶段学习的编译链接,我们可以知道,
如果我们在a.cpp中调用了某个函数,但是函数是在b.cpp中定义的,所以函数的的地址就会在b.obj中。在a中就无法找到,那么怎么办呢?
链接阶段就是专门处理这种问题,链接器看到a.o调用函数,但是没有Add的地址,就会到b.o的符号表中找函数的地址,然后链接到一起
c++基础及其STL|c++基础篇——(一)c++快速入门(上)
文章图片

c++基础及其STL|c++基础篇——(一)c++快速入门(上)
文章图片

那么链接时,面对函数,链接器会怎么去寻找函数呢?
我们可以举一下例子:
我们将这段代码分别送到c和c++编译器里面去编译
int Add(int x, int y); double Add(double x, double y); int Sub(int x, int y);

首先,我们的函数都没有定义,所以这个程序肯定是要报错的
但是,我们关注的是c和c++的错误信息
这是c++错误信息
c++基础及其STL|c++基础篇——(一)c++快速入门(上)
文章图片

这是c的错误信息
c++基础及其STL|c++基础篇——(一)c++快速入门(上)
文章图片

我们可以得出结论:c++在形成符号表的时候,会根据函数的参数对函数名进行修饰,所以可以允许重名,而c的函数名却不会修饰,所以会导致重名的问题
函数名不相同,其生成的函数地址也不会相同,所以在调用的时候也不会产生冲突
那么,以下的函数构不成重载?
int F(int a); int F(int a=0);

【c++基础及其STL|c++基础篇——(一)c++快速入门(上)】当然不构成,因为它们的参数类型是相同的

    推荐阅读