1979年,贝尔实验室的本贾尼等人试图分析unix内核的时候,试图将内核模块化,于是在C语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为
C with classes
。
C++98
:C++标准第一个版本,绝大多数编译器都支持,得到了国际标准化组织(ISO)和美国标准化协会认可,以模板方式重写C++标准库,引入了STL(标准模板库)
C++11
:增加了许多特性,使得C++更像一种新语言,比如:正则表达式、基于范围for循环、auto关键字、新容器、列表初始化、标准线程库等
C++14
:对C++11的扩展,主要是修复C++11中漏洞以及改进,比如:泛型的lambda表达式,auto的返回值类型推导,二进制字面常量等
除此之外还有C++1.0,2.0,03,05,17,20等,但都不是那么重要
C++共有63个关键字相对于C的32个相当于翻倍(
兼容C关键字
)
asm | do | if | return | try | continue |
auto | double | inline | short | typedef | for |
bool | dynamic_cast | int | signed | typeid | public |
break | else | long | sizeof | typename | throw |
case | enum | mutable | static | union | wchar_t |
catch | explicit | namespace | static_cast | unsigned | default |
char | export | new | struct | using | friend |
class | extern | operator | switch | virtual | register |
const | false | private | template | void | true |
const_cast | float | protected | this | volatile | while |
delete | goto | reinterpret_cast |
许多相同的变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题
下面是常规命名空间使用
namespace My_Space // My_Space为命名空间的名称 { // 命名空间中的内容,既可以定义变量,也可以定义函数 int a; int Add(int left, int right) { return left + right; } }
注意1
:命名空间可以嵌套namespace My_Space1 { int a; int b; int Add(int left, int right) { return left + right; } namespace My_Space2//嵌套 { int c; int d; int Sub(int left, int right) { return left - right; } } }
注意2
:同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中namespace My_Space // My_Space为命名空间的名称 { // 命名空间中的内容,既可以定义变量,也可以定义函数 int a; int Add(int left, int right) { return left + right; } } namespace My_Space // My_Space为命名空间的名称 { // 命名空间中的内容,既可以定义变量,也可以定义函数 int b; int Mul(int left, int right) { return left * right; } }相当于
namespace My_Space // My_Space为命名空间的名称 { //上 int a; int Add(int left, int right) { return left + right; } //下 int b; int Mul(int left, int right) { return left * right; } }
1.加命名空间名称及作用域限定符’
::
'int main() { printf("%d\n", My_Space::a); return 0; }
2.使用
using
将命名空间中成员引入using My_Space::b; int main() { printf("%d\n", b); return 0; }3.使用
using namespace 命名空间名称
引入using namespce My_Space; int main() { printf("%d\n", My_Space::a);//可以这样 printf("%d\n", b);//也可以直接使用 Add(10, 20); return 0; }
注意
:
使用cout标准输出(控制台)和cin标准输入(键盘)时必须包含< iostream >头文件以及std标准命名空间
关于C++中没有‘.h’的解释
:
早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中。后来将其实现在std命名空间下
,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h 旧编译器(vc 6.0)中还支持iostream.h格式,后续编译器已不支持,所以应使用<iostream>+std
的方式
基本使用方法(粗略了解)
cout
相当于printf
cin
相当于scanf
endl
相当于换行符‘\n
’#include <iostream> using namespace std; int main() { int a; double b; char c; cin>>a; cin>>b>>c; cout<<a<<endl; cout<<b<<" "<<c<<endl; //不像printf,这里必须要用 输出流符号<< 来连接 return 0; }
定义
:调用函数时可传参可不传,不传时使用函数自己指定的实参,如例子所示:void TestFunc(int a = 0) { cout<<a<<endl; } int main() { TestFunc(); // 没有传参时,使用参数的默认值 TestFunc(10); // 传参时,使用指定的实参 }
void TestFunc(int a = 10, int b = 20, int c = 30);
void TestFunc(int a, int b = 10, int c = 20);
注意
:
半缺省参数必须从右往左依次来给出,不能间隔着给
缺省参数不能在函数声明和定义中同时出现
(如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用哪个缺省值
)缺省值必须是常量或者全局变量
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 main() { Add(10, 20); Add(10.0, 20.0); Add(10L, 20L); return 0; }
以下不是函数重载
short Add(short left, short right) { return left+right; } int Add(short left, short right) { return left+right; }
程序的运行,需要经历:
预处理、编译、汇编、链接
参考:C语言----程序编译(预处理)
在Linux下
:(假设a.cpp中调用了b.cpp中定义的Add函数
)
链接阶段,链接器看到a.o
(二进制文件)调用Add,但是没有Add的地址,就会到b.o
(二进制文件)的符号表中找Add的地址,然后链接到一起
在调用函数时一般会使用
汇编指令call
参见:函数栈帧的创建和销毁(详细)
形如
:80489bc: e8 73 ff ff ff call <?>
(问号也就是函数签名)
每个编译器都有自己的函数名修饰规则
gcc编译器
:
使用objdump工具,键入objdump -S 源文件
函数签名依然是Add
g++编译器
:
同样的操作显示出的函数签名变为了<_Z3Addii>
而不是原函数名Add
这里我们已经可以得出结论
:
在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中,构成函数签名
回到链接阶段
如果b.cpp中有两个Add函数,由于在gcc编译器下会发现符号表中有两个重名的函数签名,所以会直接报错,因为不知道该拿出哪个地址。但g++就很明确了,两个相同函数名的函数签名不一样,所以可以轻松取出目标地址
这样一来,也可以说明上面不是函数重载的情况(
与返回值无关
)
在Windows下
:
对于C语言来说