C++ 面向对象
一、C++三大特性
记忆口诀
三大特性记分明,封装继承多态行;
封装数据和操作,权限控制安全定;
继承复用加扩展,子类父类心相印;
多态接口行为异,编译运行两类型。
核心概念
- 封装:数据与操作打包,通过访问权限控制暴露(public/private/protected),提高安全性,隐藏实现细节
- 继承:子类拥有父类属性和行为,可在原有基础上扩展,实现代码复用
- 多态:同一种接口不同行为,分编译时多态(函数重载、运算符重载)和运行时多态(虚函数+继承)
代码示例
1 |
|
二、重载与重写
记忆口诀
重载重写要分清,作用时机不相同;
重载同类名相同,参数不同编译定;
重写继承父虚函,函数签名要一致;
运行绑定用多态,override关键字记。
重载(Overload)
- 定义:同一作用域内,函数名相同但参数列表不同
- 特点:编译期绑定(静态多态),与返回值无关
重写(Override)
- 定义:派生类重写基类虚函数,函数签名完全相同
- 特点:运行期绑定(动态多态),需用virtual和override关键字
代码示例
1 | // 重载示例 |
三、访问修饰符
记忆口诀
访问权限有三种,public、private和protected;
公有成员随便用,私有只能内部通;
保护成员加一层,子类也能来访问。
核心概念
- public:类内外都可访问
- private:仅类内部可访问
- protected:类内部和派生类可访问
四、多重继承
记忆口诀
多重继承多基类,功能强大风险藏;
菱形继承问题现,二义性来把人伤;
虚继承来解难题,共享基类实例创。
核心概念
- 定义:一个类从多个基类继承属性和行为
- 问题:菱形继承会导致二义性(同一基类在派生类中出现多次)
- 解决:虚继承(virtual)确保基类在最终派生类中只存在一个实例
代码示例
1 | // 虚继承解决菱形问题 |
五、多态的实现机制
记忆口诀
多态实现靠虚函,四个步骤记心间;
基类声明加virtual,派生重写override添;
基类指针指派生,调用方法运行辨;
底层依赖vtable,虚指针来把表联。
实现步骤
- 基类声明虚函数(virtual关键字)
- 派生类重写虚函数(override关键字)
- 使用基类指针/引用指向派生类对象
- 通过基类指针/引用调用虚函数
底层机制
- 虚函数表(vtable):每个含虚函数的类都有一个vtable,存储虚函数地址
- 虚指针(vptr):每个对象内含一个vptr,指向所属类的vtable
- 动态绑定:运行时通过vptr找到vtable,调用对应函数
六、成员与静态成员
记忆口诀
成员静态要区分,所属对象与类分;
成员函数带this,访问变量实例跟;
静态函数无this,只能访问静态存;
静态变量类共享,类外定义初始化。
成员函数与成员变量
- 成员函数:属于对象,可访问成员变量,通过对象调用
- 成员变量:每个对象一份,随对象创建和销毁
静态成员函数与静态成员变量
- 静态成员函数:属于类,无this指针,不能直接访问非静态成员
- 静态成员变量:所有对象共享,需在类外定义和初始化
代码示例
1 | class MyClass { |
七、构造函数与析构函数
记忆口诀
构造析构特殊函,生命周期来掌管;
构造函数无返回,与类同名可重载;
默认带参拷贝委,各司其职来创建;
析构函数波浪号,资源释放要做好。
构造函数
- 定义:创建对象时自动调用,用于初始化对象
- 特点:函数名与类名相同,无返回类型,可以重载
- 种类:默认构造、带参构造、拷贝构造、委托构造
析构函数
- 定义:对象销毁时自动调用,用于释放资源
- 特点:函数名前加~,无参数,不能重载
代码示例
1 | class MyClass { |
八、虚函数与纯虚函数
记忆口诀
虚函数有实现,派生可选重写;
纯虚函数等号零,强制派生实现它;
抽象类含纯虚函,不能实例只能继承;
接口规范靠它们,多态机制顶呱呱。
虚函数
- 定义:基类中用virtual声明的函数,可在派生类中重写
- 特点:有默认实现,派生类可选重写,包含虚函数的类可实例化
纯虚函数
- 定义:没有实现的虚函数(virtual func() = 0)
- 特点:派生类必须实现,包含纯虚函数的类为抽象类,不能实例化
代码示例
1 | // 虚函数 |
九、虚析构函数
记忆口诀
虚析构函数很重要,多态删除离不了;
基类指针指派生,delete时析构全调用;
若无虚析构来帮忙,资源泄漏把祸闯。
核心概念
- 定义:带virtual关键字的析构函数
- 作用:确保通过基类指针删除派生类对象时,正确调用派生类析构函数,避免资源泄漏
代码示例
1 | class Base { |
十、不能声明为虚函数的函数
记忆口诀
虚函数有例外,以下函数不能改;
构造函数最明显,对象未建vptr未;
静态友元普通函,无继承无this在;
内联函数编译展,动态绑定冲突来。
不可声明为虚函数的函数
- 构造函数:对象未完全创建,vptr未初始化
- 普通函数(非成员函数):无继承特性,无意义
- 静态成员函数:属于类而非对象,无this指针
- 友元函数:C++不支持友元函数继承
- 内联成员函数:内联编译与虚函数动态绑定矛盾
十一、深拷贝与浅拷贝
记忆口诀
深拷贝,资源复制彻底分;
每个对象有自己的内存根;
浅拷贝,资源共享问题生;
重复释放要小心。
深拷贝
- 定义:完全复制对象及其内部动态分配的资源
- 特点:新对象与原对象完全独立,需手动管理内存
浅拷贝
- 定义:仅复制对象值,不复制内部动态分配资源
- 特点:新对象与原对象共享资源,可能导致重复释放
代码示例
1 | // 深拷贝示例 |
十二、运算符重载
记忆口诀
运算符重载函数藏,本质还是函数样;
算术关系非成员,赋值下标必须藏;
递增递减建议藏,箭头必须成员当;
特殊运算符别乱抢,原有语义要保障。
核心概念
- 本质:函数重载,函数名为"operator运算符"
- 调用方式:可直接使用运算符(a+b)或函数调用形式(operator+(a,b))
规则与建议
- 算术/关系运算符:建议非成员函数,保持对称性
- 赋值运算符:必须是成员函数
- 下标运算符:必须是成员函数,建议提供const和非const版本
- 递增/递减运算符:建议成员函数,区分前置/后置版本
- 箭头运算符(->):必须是成员函数
特殊注意
- 不建议重载:逗号、取地址、逻辑与、逻辑或(破坏原有语义或求值顺序)
- 输入/输出运算符:建议非成员函数,需定义为友元以访问私有成员
- Lambda表达式:被编译器翻译为未命名类的未命名对象,捕获列表对应类的数据成员