C++特性
一、C++常用特性
基础特性:
- 面向对象编程 (OOP)
- 类(class)和对象(object)
- 封装、继承、多态
- 构造函数和析构函数
- STL容器
- std::vector、std::map
- 函数
- 重载
- 默认参数
- 模板
- 类模板
- 函数模板
- 异常处理 try、catch、throw
- 多线程 std::thread、std::mutex、std::async、std::future
版本特性:
- C++98 (1998年),首个国际标准版本,奠定了C++的基础。
- C++03 (2003年),对 C++98 的小幅修订,主要修复了一些问题。
- C++11 (2011年),重大更新,引入了自动类型推导(auto)、智能指针、lambda表达式等新特性、nullptr。
- C++14 (2014年),对 C++11 的补充,增强了泛型编程和 lambda 表达式的功能。
- C++17 (2017年),引入了结构化绑定(std::make_pair)、std::optional、std::filesystem等新特性。
- C++20 (2020年),新增了概念(Concepts)、范围(Ranges)、协程(Coroutines)等重大特性。
二、基础特性
2.1 多态
字面意思是多种形态,实际上是指:
- 同一个函数,对不同的类对象表现出不同的行为;
- 父类的指针或引用可以指向子类对象,并调用子类重写的方法。
当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。简而言之就是基类和派生都用到同一个函数,但是定义不一样。需要在基类使用关键字virtual。
静态多态(编译时多态是指在编译阶段就能确定调用哪个函数):重载、模板
动态多态(运行时多态是指在程序运行时才能确定调用哪个函数):虚函数和继承
2.2 虚函数
// 使用virtual关键字声明函数
virtual 返回类型 函数名(参数列表);
// 纯虚函
virtual 返回类型 函数名(参数列表) = 0;
- 纯虚函数没有函数体(即没有实现)。
- 包含纯虚函数的类称为抽象类。
- 抽象类不能直接创建对象。
- 抽象类只能作为基类。
- 派生类必须实现纯虚函数:如果一个派生类没有实现基类中的所有纯虚函数,那么该派生类也会成为抽象类。
- 抽象类适合作为接口。
在 C++ 中,抽象类是不能直接实例化的。如果尝试直接创建抽象类的对象,编译器会报错。这是因为抽象类中包含至少一个纯虚函数,而纯虚函数没有实现,因此抽象类是一个不完整的类型,无法创建对象。
error: cannot declare variable 'obj' to be of abstract type 'AbstractClass'
2.3 虚函数表与虚函数表指针
虚函数表是一个存储虚函数地址的数组,每个包含虚函数的类都有一个对应的虚函数表(虚函数表是占用内存的)。目的是为了当调用虚函数时,程序通过虚函数表查找并调用正确的函数实现。就比如一个派生类如果重写了基类的虚函数,派生类的虚函数表中会替换为派生类的函数地址。反之,如果没有重写,则派生类会继承基类的实现,派生类的虚函数表中会使用基类的函数地址。
虚函数表指针(vptr)是一个指向虚函数表的指针,每个包含虚函数的对象在内存中都有一个隐藏的虚函数表指针。虚函数表指针是对象的一部分,在内存上应该跟成员变量是放在一起的;
函数表和虚函数表指针的工作原理:
- 编译阶段:
- 编译器为每个包含虚函数的类生成一个虚函数表。
- 编译器在每个对象的内存布局中添加一个
vptr
。
- 运行时:
- 当通过基类指针或引用调用虚函数时:
- 程序通过对象的
vptr
找到虚函数表。 - 根据虚函数表中的条目调用正确的函数
- 程序通过对象的
- 当通过基类指针或引用调用虚函数时:
2.4 STL容器
STL是指C++标准模板库,包含了容器、迭代器、算法、函数、一些其他辅助功能,功能强大。
STL容器部分常用的就是std::vector
、std::list
、std::map
、std::set
容器 | 特点 | 底层实现 | 存储状态 |
---|---|---|---|
std::vector |
支持随机访问;尾部插入和删除高效; 需要预分配内存,可能引发内存重新分配; |
动态数组 | 内存连续 |
std::list |
任意位置插入和删除高效;不支持随机访问; | 双向链表 | 内存不连续 |
std::map |
键值对集合,键唯一;基于键自动排序;插入、删除和查找高效 | 红黑树 | 元素按键排序存储,内存不连续 |
std::set |
有序集合,元素唯一;基于值自动排序;插入、删除和查找高效 | 红黑树 | 元素按值排序存储,内存不连续 |