我们在C语言的基础之上进行c++语言的学习。对于我们的c++语言来说,c++兼容C语言,所以我们以前编写的C语言的程序在c++平台上也是可以运行的。唯一不同的就是我们的c++对于我们C语言的部分语法做出了优化以及引入了面向对象的概念。所以在刚开始学习c++的时候我们可以从了解c++新增的语法入手,学习c++语言的特点。
🌵命名空间域
我们先来看一段代码:
我们定义了一个变量名叫做 rand 的变量。我们可以发现程序运行一切正常,但是如果我们再引入一个头文件呢? 我们会发现编译器产生了报错,显示rand变量已经定义为一个函数。我们可以很容易的想到这是和我们stdlib.h库里面的rand函数发生了冲突。但是我们不可能记住所有库中的变量名并在命名的时候加以回避,那么也就代表着我们在定义变量的时候随时都可能会有和库中的变量发生冲突的危险。这是C语言当中隐藏的危险。
所以我们的c++为了避免出现这种情况引入了命名空间域的概念。对于c++我们会经常看到如下的代码:
我们可以逐步的进行分析:我们第一行引用的iostream我们可以先将其认为是和我们stdio.h类似的头文件。但是我们这个头文件是处于特定的命名空间域当中的,只是单纯的包含这个头文件并不能使用其中的函数,所以我们需要将我们这个命名空间域展开。就有了我们第三行的代码:
using namespace std;
我们为了方式我们在全局的范围内定义的变量名和我们库函数当中的函数名相冲突所以自己创建了一个命名空间域。所以也就有了:
namespace lm
{
int rand = 12;
}
但是我们创建好命名空间域之后并不能直接使用我们在其中定义的变量。我们有两个选择要么向我们展开std的那样展开。但是我们需要注意的是,要是我们将命名空间域展开之后,相当于我们命名的变量会直接出现在全局的范围内,依旧会出现冲突,所以我们在展开命名空间域的时候需要格外小心。所以我们是用另一种形式——使用域作用限定符进行指定域中的变量。也就有了我们的:
printf("%d", lm::rand);
这么看来我们的命名空间域很实用,并且我们的命名空间域支持嵌套,我们可以在一个命名空间域中嵌套一个新的命名空间域,在使用的时候只需要依次利用域作用限定符将我们的变量名引出即可。
🌵c++的输入和输出
实际上按照我们c++正规的写法来说我们上面的代码应该这样来写:
我们在main函数当中的输出函数由printf更改为了cout。这是c++当中的输出函数。其优点我们到后面会细细道来。我们先来了解一下cout函数的使用方法:
我们可以将cout大致理解为我们屏幕上面的黑框框,我们可以将指定的内容输出到我们的黑框框当中,我们在上面也就是将我们lm1命名空间域中的a输出到屏幕上。双箭头表示输出方向,endl表示我们本行输入的结束。
既然有了输出函数那么一定有输入函数,在c++当中输入函数为:
我们先使用cout函数在屏幕上打印提示信息,之后使用cin检测用户的输入,最后使用cout将我们输入的x打印出来。由于我们的c++是兼容C语言的所以我们可以将我们的cin,cout,printf,scanf搭配起来使用。样例如下:
需要注意的是,虽然我们的printf函数可以和cout混合使用,但是效率方面会有些许减慢,所以我们在使用的时候尽量不要掺杂使用。
同时我们的cout函数会自动检测并识别类型,也就是说我们在使用cout函数向屏幕输出的时候,不需要指定格式输出,代码如下:
🌵c++的缺省函数
在我们的c++语言当中还支持缺省函数的概念。我们先来通过一段代码体会一下缺省函数的概念: 就像我们上面的代码所展示的那样,我们可以在定义函数时候给我们的参数定义一个默认值,这样假如我们在使用函数的时候可以选择只传入一个参数,另一个参数会自动默认会定义的值。我们也可以向函数中传入两个值。代码如下:
缺省函数分为两种全缺省函数和半缺省函数,半缺省函数就像是我们上面的代码一样,全缺省的代码如下:
在这里需要我们注意的是:我们在选择半缺省的时候,缺省的值必须在后面,否则系统可能会报错。还有我们在向函数传值的时候不能跳过数据进行传参,否则系统也会报错。
前半部分缺省报错:
跳过参数传参报错:
和python语言不同的是我们这里的缺省函数不能指定参数传参,否则也会报错:
🌵c++函数重载
首先我们来看一下函数重载的定义:函数重载是函数的一种特殊的情况。c++允许在同一作用域中声明几个功能类似的同名的函数,这些同名函数的形参列表(参数个数,参数类型或参数顺序)不同,常用来处理实现功能类似,数据类型不同的问题。
我们首先通过两个简单的函数来体会一下函数重载:
在C语言当中我们的编译器并不支持同名的函数,但是我们的c++将这一点优化之后,可以支持我们的同名但是参数的形式不同的函数。这种参数不同但是函数名相同的函数成为函数的重载。在这里需要我们注意的是:当我们的形参列表相同但返回值不同时不构成重载,否则会编译出错。
有一个特殊的情况:根据定义当我们有一个全缺省函数和我们的无参数的函数构成重载的时候在编译上会通过。 但是当我们在使用函数缺省的时候就会出现解释歧义的现象,进而产生报错:
在介绍完c++的重载之后我们肯定会想:为什么C语言不支持函数重载,c++就可以支持函数重载呢?c++又是怎样支持函数的重载的呢?
我们先来给定一个正确的答案,再来进行详细的解释:我们的c++语言在编译链接的过程当中会通过函数名修饰规则支持重载。
我们先从编译器的编译链接的过程来解释这一答案:
通过汇编代码我们可以发现在我们的C语言当中产生的汇编指令如下:
我们的函数名表示的形式仅仅是我们定义出来的函数名,所以当我们定义两个相同的函数名的时候就出现同一个函数名对应多个函数地址的情况,进而产生歧义。而我们再来看我们c++的汇编代码的形式:
我们可以发现的是我们在汇编当中产生的函数名并不只我们定义的函数名,他会通过一种特定的形式加以修饰。在我们的gcc编译器下所进行的修饰为把我们的参数的所写添加到我们的函数名当中,这样定义不同的参数的同名函数所最终找到的地址就不同了。也就不会产生歧义了。这也就是我们函数重载的原理。