前言
这里只是简单列出C++语言与虚拟(virtual)
总述:虚拟机制的核心价值
虚拟(virtual)机制是C++实现运行时多态的核心语法,通过动态绑定(Dynamic Binding) 实现面向对象编程的三大特性之一——多态性。其本质是在运行时根据对象类型决定调用哪个函数版本,主要解决以下问题:
- 基类指针/引用调用派生类方法的问题
- 对象类型识别(RTTI) 的底层支持
- 接口与实现分离的设计需求
- 可扩展框架的构建基础
核心组件:虚函数 | 抽象类 | 虚继承 | 虚析构函数 | 动态类型转换
分述:虚拟语法体系详解
一、虚函数(Virtual Functions)
1. 基本语法与原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Base { public: virtual void func() { cout << "Base::func()" << endl; } };
class Derived : public Base { public: void func() override { cout << "Derived::func()" << endl; } };
Base* b = new Derived(); b->func();
|
关键机制:
- 虚函数表(vtable):每个含虚函数的类拥有一个虚表
- 虚指针(vptr):每个对象隐含指针指向虚表
- 动态绑定:运行时通过vptr查找调用正确函数
2. override 与 final 限定符(C++11)
1 2 3 4 5 6 7 8 9 10 11 12
| class Derived2 : public Derived { public: void func() final { cout << "Derived2::func()" << endl; } };
class Derived3 : public Derived2 { public: };
|
二、纯虚函数与抽象类
1. 纯虚函数定义
1 2 3 4 5
| class Shape { public: virtual double area() const = 0; virtual void draw() = 0; };
|
2. 抽象类特性
- 不能实例化:
Shape s; 会导致编译错误
- 强制接口实现:派生类必须实现所有纯虚函数
- 可包含实现:抽象类可提供普通成员函数实现
三、虚析构函数(Critical!)
1. 必要性演示
1 2 3 4 5 6 7 8 9 10 11 12
| class Base { public: ~Base() { cout << "~Base()" << endl; } };
class Derived : public Base { public: ~Derived() { cout << "~Derived()" << endl; } };
Base* b = new Derived(); delete b;
|
2. 正确实现
1 2 3 4 5 6 7 8
| class Base { public: virtual ~Base() { cout << "~Base()" << endl; } };
delete b;
|
黄金规则:任何作为基类的类型必须声明虚析构函数
四、虚继承(Virtual Inheritance)
1. 解决菱形继承问题
1 2 3 4 5
| classDiagram class A class B : virtual public A class C : virtual public A class D : public B, public C
|
2. 语法实现
1 2 3 4 5 6 7
| class A { int data; }; class B : virtual public A {}; class C : virtual public A {}; class D : public B, public C {};
D d; d.data = 10;
|
底层机制:
- 虚基类表(vbtable):存储虚基类偏移量
- 共享实例:虚基类在派生类中只有一份拷贝
五、RTTI(运行时类型识别)
1. typeid 运算符
1 2 3 4
| Base* ptr = new Derived(); if (typeid(*ptr) == typeid(Derived)) { cout << "指向Derived对象" << endl; }
|
2. dynamic_cast 转换
1 2 3 4 5
| Base* b = new Derived(); Derived* d = dynamic_cast<Derived*>(b);
Base* b2 = new Base(); Derived* d2 = dynamic_cast<Derived*>(b2);
|
前提条件:基类至少包含一个虚函数(多态类型)
六、协变返回类型(Covariant Return Types)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Base { public: virtual Base* clone() const { return new Base(*this); } };
class Derived : public Base { public: virtual Derived* clone() const override { return new Derived(*this); } };
|
应用实践:虚拟机制的高级用法
1. 工厂模式(Factory Pattern)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Product { public: virtual void operation() = 0; virtual ~Product() {} };
class Creator { public: virtual Product* createProduct() = 0; virtual ~Creator() {} };
class ConcreteCreator : public Creator { public: Product* createProduct() override { return new ConcreteProduct(); } };
|
2. 访问者模式(Visitor Pattern)
1 2 3 4 5 6 7 8 9 10 11 12
| class Element { public: virtual void accept(Visitor& v) = 0; virtual ~Element() {} };
class Visitor { public: virtual void visit(ElementA&) = 0; virtual void visit(ElementB&) = 0; virtual ~Visitor() {} };
|
3. 策略模式(Strategy Pattern)
1 2 3 4 5 6 7 8 9 10 11
| class SortingStrategy { public: virtual void sort(vector<int>&) const = 0; virtual ~SortingStrategy() {} };
class QuickSort : public SortingStrategy { }; class MergeSort : public SortingStrategy { };
context.setStrategy(new QuickSort());
|
性能分析与优化
虚函数开销来源
| 开销类型 |
说明 |
典型值 |
| 间接调用开销 |
虚函数表查找 |
1-3个时钟周期 |
| 缓存不友好 |
vptr导致缓存失效 |
视情况而定 |
| 代码膨胀 |
虚表存储空间 |
每类4-8字节+虚表大小 |
| 内联限制 |
虚函数无法内联 |
关键路径损失大 |
优化策略
- 虚函数缓存:对频繁调用的虚函数结果缓存
- 模板+CRTP:编译期多态替代运行时多态
1 2 3 4 5 6 7 8 9 10
| template <typename T> class Base { void interface() { static_cast<T*>(this)->implementation(); } };
class Derived : public Base<Derived> { void implementation(); };
|
- final类优化:标记不需要进一步继承的类
1 2 3
| class Leaf final : public Base { };
|
总结:虚拟机制的最佳实践
核心原则
- 虚析构规则:多态基类必须声明虚析构函数
- 接口清晰化:使用
override明确重写关系
- 抽象约束:不应实例化的类声明纯虚函数
- 继承控制:合理使用
final限制继承链
- RTTI节制:避免过度依赖
dynamic_cast
应用场景决策树
1 2 3 4 5 6 7
| graph TD A[需要运行时多态?] --是--> B[需要接口约束?] A --否--> C[使用模板/静态多态] B --是--> D[定义抽象类] B --否--> E[使用普通虚函数] D --> F[派生类实现接口] E --> G[注意虚析构函数]
|
C++11/14/17增强特性
| 特性 |
版本 |
作用 |
override |
C++11 |
明确重写关系 |
final |
C++11 |
禁止重写/继承 |
| 委托构造函数 |
C++11 |
简化构造链 |
| 继承构造函数 |
C++11 |
提升代码复用 |
[[nodiscard]] |
C++17 |
虚函数返回值检查 |
版权声明: 此文章版权归曦曦所有,如有转载,请注明来自原作者