运行时多态
1. 虚函数重写
虚函数重写是指在派生类中重新定义基类中已声明为虚函数的函数。
虚函数重写的工作原理:
- C++通过虚函数表(vtable)和虚表指针(vptr)实现运行时多态。
- 每个具有虚函数的类都有一个虚函数表,该表包含指向类中所有已定义虚函数的指针。
- 对象中包含一个指向该表的指针,称为虚表指针,它指向对象所属类的虚函数表。
虚函数表:
- 一个类如果有虚函数,编译器会为该类生成一个虚函数表,表中包含指向类中所有虚函数的指针。
虚表指针:
- 每个对象都有一个虚表指针,它是一个指向类虚函数表的指针。
多个派生类是否共享基类的虚函数表:
- 不共享。每个类都有自己的虚函数表,即使是从基类继承的虚函数,派生类的虚函数表也会包含这些函数的条目。
类的多个对象是否共享类的虚函数表:
- 是的,类的多个对象共享同一个类的虚函数表,但每个对象都有自己的虚表指针,指向同一个表。
案例代码:
class Base { public: virtual void show() { cout << "Base show" << endl; } virtual ~Base() {} }; class Derived : public Base { public: void show() override { cout << "Derived show" << endl; } ~Derived() {} }; void func(Base* b) { b->show(); // 运行时多态 } int main() { Base* b = new Derived(); func(b); // 输出 Derived show delete b; return 0; }
2. 纯虚函数
纯虚函数是在基类中声明但没有定义的虚函数,它要求派生类必须提供具体的实现。
案例代码:
class Shape { public: virtual void draw() const = 0; // 纯虚函数 }; class Circle : public Shape { public: void draw() const override { cout << "Drawing a circle" << endl; } }; int main() { Shape* shape = new Circle(); shape->draw(); // 输出 Drawing a circle delete shape; return 0; }
3. 抽象类
抽象类是包含至少一个纯虚函数的类。它不能被直接实例化,但可以作为其他类的基类。
案例代码:
class Animal { public: virtual void speak() const = 0; // 纯虚函数 }; class Dog : public Animal { public: void speak() const override { cout << "Woof!" << endl; } }; int main() { // Animal a; // 错误:Animal是抽象类,不能实例化 Dog d; // 正确:Dog是非抽象类,可以实例化 d.speak(); // 输出 Woof! return 0; }
4. 虚析构
虚析构是声明为虚的析构函数,它确保在删除基类指针时能够调用正确的析构函数。
案例代码:
class Base { public: virtual ~Base() { cout << "Base destructor" << endl; } }; class Derived : public Base { public: ~Derived() { cout << "Derived destructor" << endl; } }; int main() { Base* b = new Derived(); delete b; // 调用 Derived 的析构函数,然后调用 Base 的析构函数 return 0; }
在上述代码中,即使通过基类指针删除派生类对象,也会按正确的顺序调用派生类和基类的析构函数。这是通过虚析构函数实现的,它确保了正确的资源清理。
作者:
hwaityd
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)