C++初识
1 C++的前世今生
1.1 什么是C++
C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度
的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object
oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语
言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而产生的,它既可以进行C语
言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程
序设计。
就是下面这位大佬发明的C++
怎么样狠帅吧!
1.2 C++发展史
1979年,贝尔实验室的本贾尼等人试图分析unix内核的时候,试图将内核模块化,于是在C语言的基础上进
行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为C with classes。
后来不断完善和进化。
1.3 C++的重要性
1.3.1 语言使用广泛度
一般将C和C++放在一起
1.3.2 学习和工作
个人认为深入学习C++和C语言,对理解其他编程语言有很大的帮助。工作上,用到C++的开发也很多。
2 C++入门
2.1 C++关键字
C++有61个关键字,C语言有32个关键字。
2.2 命名空间
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作
用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字
污染,namespace关键字的出现就是针对这种问题的。
2.2.1 命名空间定义
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名
空间的成员。
//1. 普通的命名空间
namespace N1 // N1为命名空间的名称
{
// 命名空间中的内容,既可以定义变量,也可以定义函数
int a;
int Add(int left, int right)
{
return left + right;
}
}
//2. 命名空间可以嵌套
namespace N2
{
int a;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N3
{
int c;
int d;
int Sub(int left, int right)
{
return left - right;
}
}
}
//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
namespace N1
{
int Mul(int left, int right)
{
return left * right;
}
}
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
2.2.1 命名空间使用
命名空间中成员该如何使用呢?比如:
namespace N {
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", a); // 该语句编译出错,无法识别a
return 0;
}
命名空间的使用有三种方式:
- 加命名空间名称和作用域限定符
int main()
{
printf("%d\n", N::a);
return 0;
}
- 使用using将命名空间中成员引入
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
- 使用using namespace 命名空间名称引入,但是这种做法过于暴力,容易命名冲突,在实际的开发中不建议用。
using namespce N;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
Add(10, 20);
return 0;
}
2.3 输入&输出
直接上代码:
#include<iostream>
using namespace std;
int main()
{
cout<<"Hello world!!!"<<endl;
return 0;
}
- 使用cout标准输出(控制台)和cin标准输入(键盘)时,必须包含< iostream >头文件以及std标准命名空
间。
注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件
即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文
件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用
+std的方式。- 使用C++输入输出更方便,不需增加数据格式控制,比如:整形–%d,字符–%
2.4 缺省参数
2.4.1 缺省参数概念
大家知道什么是备胎吗?C++中函数的参数也可以配备胎。
缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该
默认值,否则使用指定的实参。
void TestFunc(int a = 0) {
cout<<a<<endl; }
int main()
{
TestFunc(); // 没有传参时,使用参数的默认值
TestFunc(10); // 传参时,使用指定的实参
}
2.4.2 缺省参数分类
- 全缺省参数
void TestFunc(int a = 10, int b = 20, int c = 30) {
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl; }
- 半缺省参数
void TestFunc(int a, int b = 10, int c = 20) {
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
注意:
半缺省参数必须从右往左依次来给出,不能间隔着给
缺省参数不能在函数声明和定义中同时出现
2.5 函数重载
自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。
比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前
者是“谁也赢不了!”,后者是“谁也赢不了!”
2.5.1 函数重载的概念
函数重载:是函数的一种特殊情况,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 main()
{
Add(10, 20);
Add(10.0, 20.0);
Add(10L, 20L);
return 0;
}
2.5.2 C++函数的重载的原理和C不可以函数重载的原因
为什么C++支持函数重载,而C语言不支持函数重载呢?
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
假设有test.h test.cpp main.c多文件结构的源文件
在链接生成执行文件的时候;因为main.cpp中调用了在test.cpp中的Mul函数,所以汇编生成的.o文件会找到Mul函数的地址,要是只是声明了Mul函数没有定义,那么就会发生链接错误,如果都正常,会找到上图中的函数地址,而且是通过函数名字去找的,这是C不能函数重载的关键因为C源程序经过预处理、编译形成的汇编代码中函数名和C++经过预处理、编译形成的汇编代码中函数名的命名规则不同,导致在同名函数存在时链接时C编译器就会不知道链接哪一个就会出错,而C++编译器则不会(在linux中说明这个问题)
型首字母】。 我在linux环境下把C和C++在编译时候的函数名问题演示一下,就明白了。
源文件:main.c和C编译器形成的目标文件:mainc C++编译器形成的目标文件:maincpp
这是main.c中的代码
objdump -S maincpp/mainc 通过这个指定可以查看汇编信息中的函数名
我们发现二者的函数名字不同,C++把参数类型的首字母和函数名字的长度也加进去了,到这C++支持函数重载,而C不支持就不言而喻了吧。