1 历史由来
本贾尼.斯特劳斯特卢普,于1979年在贝尔实验室分析UNIX系统分布式内核的流量时,特别希望有一种更加模块化的工具,于是在1979年10月时开始着手开发一块新的编程语言,在c语言的基础上增加了面向对象的机制,这就是C++。1983年完成了C++的第一个版本
2 C++与C的重要区别
① C++是完全兼容C语言的所有内容
② C++支持面向对象的编程思想
③ C++支持运算符重载、函数重载的编译时多态机制
④ C++支持泛型编程、模板机制
⑥ C++支持异常处理
⑦ C++的类型检查更加严格
⑧ C++增加了名字空间
3 第一个C++程序:helo world
#include <iostream>
using namespace std;
int main(int argc,const char* argv[])
{
cout << "hello world" << endl
return 0;
}
4 C++与C数据类型不同
4.1 结构的不同struct
不需要typedef对类型进行重定义,因为C++中设计好结构后,定义结构变量时不再需要struct关键字
结构中可以有成员函数,结构变量、指针通过.或者->访问成员函数,在成员函数中可以直接访问成员变量、成员函数,不再需要.或者->
结构中默认下一定有一些隐藏的成员函数(构造、析构、拷贝构造、赋值函数)
结构可以继承其它结构,也可以被其他结构继承
可以给成员设置访问控制属性
public 公开的(默认)
protected 保护的
private 私有的
4.2 联合的不同union
不需要typedef对类型进行重定义,因为C++中设计好联合后,定义联合变量时不再需要union关键字
联合中可以有成员函数,联合变量、指针通过.或者->访问成员函数,在成员函数中可以直接访问成员变量、成员函数,不再需要.或者->
联合中默认下一定有一些隐藏的成员函数(构造、析构、拷贝构造、赋值函数)
可以给成员设置访问控制属性
public 公开的(默认)
protected 保护的
private 私有的
4.3 枚举的不同enum
不需要typedef对类型进行重定义,因为C++中设计好枚举后,定义枚举变量时不再需要enum关键字
是一种独立的数据类型(C语言用int来模拟枚举类型),不能与整型做隐式转换,只能用枚举常量
4.4 bool类型的不同
C++中有真正的布尔类型,bool是C++中的关键字,不需要包含stdbool.h头文件,true和false也是C++的关键字
true和false在C++中是1字节,并且是真正的布尔类型,而c语言中是int类型模拟的,是4字节,但是bool类型字节数都是1
4.5 字符串类型的不同
C++中的字符串都被封装在string类中,可以与C语言的字符串进行转换 (.c_str()从string转为char*)
string类被封装在string头文件中,该头文件被包含在了iostream头文件中,属于std名字空间
使用string字符串可以通过运算符的方式直接操作字符串,原来C语言string.h系列函数也可以继续使用
4.6 void*类型的不同
在C语言中,void*可以与任意类型的指针进行转换;在C++中,void*不可以自动隐式转换成其他类型的指针,如果需要赋值给其他类型的指针时,必须强制类型转换,为了提高指针的安全性考虑;在C++中,其他类型指针可以自动隐式转换成void*,C++之所以保留这个转换,是因为C语言标准库、操作系统接口函数采用了大量的void*作为函数参数,如果不保留该转换,C++在调用此类函数时会非常麻烦。例如free/realloc/bzero/mmap
5 C++名字空间
5.1 为什么需要名字空间?
由于C++完全兼容C语言,标准库中自带了大量的宏、函数、结构、类,而且还支持继承语法,导致全局的标识符大量增加,命名冲突的风险也大大增加。
5.2 什么是名字空间
C++中设计一种对命名空间进行逻辑划分单位的技术,称为名字空间,是一种解决命名冲突的机制。定义名字空间后,就形成了命名的封闭作用域
namespace xxx{
变量;
函数;
结构、联合、枚举;
类;
}
5.3 如何使用名字空间
① 域限定符访问 ::
xxx::标识符;
② 全部直接访问
using namespace xxx;
注意:可以直接访问xxx名字空间中的所有标识符,虽然方便,但是不建议都这样用
③ 同名名字空间可以合并
a.cpp
namespace n1{
int a;
}
b.cpp
namespace n1{
int b;
}
main.cpp
using namespace n1;// 会把a.cpp的a和b.cpp的b一起倒入到main.cpp中
同名名字空间可以多处定义,不同位置的同名名字空间编译器会自动合并
④ 名字空间中的标识符可以声明与定义分离
a.h
namespace n1{
extern int num; // 声明
}
a.cpp
int n1::num; // 定义
注意:需要在定义时使用域限定符进行说明
⑤ 匿名名字空间
所有的全局标识符都属于同一个名字空间,该名字空间没有名字,称为匿名名字空间,只要不加域限定符说明,那默认都属于匿名名字空间的标识符
匿名名字空间中的标识符通过 ::标识符名 来访问
⑥ 名字空间可以嵌套
namespace n1{
int num = 10;
namespace n2{
int num = 20;
namespace n3{
int num = 30;
}
}
}
采用逐层分解的方式访问:
n1::n2::n3::num;
导入整个名字空间:
using namespace n1::n2::n3;
给名字空间换别名
namespace n123 = n1::n2::n3;
6 C++堆内存管理
C++中有专门管理堆内存的语句,而C语言中只能使用标准库提供的函数
语法格式:
类型* p = new 类型名;
new 分配内存,相当于C语言的malloc
delete p;
delete 释放内存,相当于C语言的free
类型* p = new 类型名(val);
new在分配内存时允许直接对内存进行初始化
数组的分配与释放
类型* p = new 类型名[个数];
分配连续多个同类型的堆内存,并且会调用多次构造函数
类似:malloc(sizeof(类型)*个数)
delete[] p;
专门用于释放通过new[]申请的内存,它会自动调用多次析构函数
注意:malloc/free、new/delete、new[]/delete[]不能混用
重复释放
delete与free一样不能重复释放,但都可以释放空指针
内存分配失败
malloc分配失败返回NULL,程序继续
new分配失败会抛出一个异常,并立即结束程序
new和malloc的返回值
malloc 返回一个void*类型的指针,需要强转
new 返回一个具体类型的指针,不需要强转
malloc/free 与 new/delete 区别?
区别 | malloc/free | new/delete |
身份 | 函数 | 运算符/关键字 |
参数 | 字节数(手动计算) | 类型名(自动计算) |
返回值 | void* | 带类型的指针 |
处理数组 | 手动计算总字节数 | new 类型[个数] |
扩容 | realloc | 无法直接处理 |
失败 | 返回NULL | 抛异常 |
构造\析构 | 不调用 | 自动调用 |
初始化 | 无法初始化 | 允许初始化 |
头文件 | 包含头文件 | 直接使用 |
函数重载 | 不允许重载 | 允许重载 |
分配内存的位置 | 堆区 | 自由存储区 |