深入解析C++虚函数表(vtable)和虚指针(vptr)
创作时间:
作者:
@小白创作中心
深入解析C++虚函数表(vtable)和虚指针(vptr)
引用
CSDN
1.
https://blog.csdn.net/karl2000/article/details/136697101
虚函数表(vtable)和虚指针(vptr)是C++实现多态性的关键机制。本文将深入解析它们的基本概念、工作原理以及在实际编程中的应用。
1. 虚函数表(vtable)和虚指针(vptr)的基本概念
每个使用虚函数的类都有一个虚函数表(vtable)。vtable是一个包含指向类虚函数的指针的数组。每个对象都有一个虚指针(vptr),指向其类的vtable。当调用对象的虚函数时,实际上是通过vptr和vtable来动态确定要调用哪个函数。
示例代码:
#include <iostream>
using namespace std;
class Base {
public:
virtual void show() { cout << "Base class show" << endl; }
};
class Derived : public Base {
public:
void show() override { cout << "Derived class show" << endl; }
};
int main() {
Base *bptr;
Derived d;
bptr = &d;
// 动态调用正确的函数(Derived::show)
bptr->show();
return 0;
}
2. 如何通过虚函数实现多态
C++中的多态性允许通过基类指针调用派生类的函数。这是通过虚函数(在基类中声明为virtual
)和自动维护的vptr和vtable实现的。
示例代码:
#include <iostream>
using namespace std;
class Animal {
public:
virtual void speak() { cout << "Some animal sound" << endl; }
};
class Dog : public Animal {
public:
void speak() override { cout << "Woof" << endl; }
};
class Cat : public Animal {
public:
void speak() override { cout << "Meow" << endl; }
};
void makeAnimalSpeak(Animal* animal) {
animal->speak();
}
int main() {
Dog dog;
Cat cat;
makeAnimalSpeak(&dog);
makeAnimalSpeak(&cat);
return 0;
}
3. 虚析构函数
使用虚析构函数确保当通过基类指针删除派生类对象时,可以正确地调用派生类的析构函数,避免资源泄露。
示例代码:
#include <iostream>
using namespace std;
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;
}
4. 纯虚函数和抽象类
纯虚函数是一种没有实现的虚函数,其唯一目的是在派生类中进行重写。包含纯虚函数的类称为抽象类,不能实例化。
示例代码:
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() = 0; // 纯虚函数
};
class Circle : public Shape {
public:
void draw() override { cout << "Drawing Circle" << endl; }
};
int main() {
// Shape s; // 错误:不能实例化抽象类
Circle c;
c.draw(); // 正确:调用Circle::draw
return 0;
}
5. 重写 vs 重载虚函数
虚函数可以在派生类中被重写,这是多态的基础。重写是指派生类提供一个与基类虚函数签名完全相同的函数实现。与之相对的,重载是在同一个类中创建相同名称但参数列表不同的函数。
示例代码:
#include <iostream>
using namespace std;
class Base {
public:
virtual void func() { cout << "Base func()" << endl; }
virtual void func(int x) { cout << "Base func(int)" << endl; }
};
class Derived : public Base {
public:
void func() override { cout << "Derived func()" << endl; }
// 注意:这不是重写,因为参数列表不同,这是重载
void func(int x) override { cout << "Derived func(int)" << endl; }
};
int main() {
Derived d;
d.func(); // 调用Derived::func()
d.func(10); // 调用Derived::func(int)
return 0;
}
本文详细介绍了C++中虚函数表(vtable)和虚指针(vptr)的概念及其在实现多态性中的作用。通过多个示例代码展示了虚函数、虚析构函数、纯虚函数和抽象类等概念,并解释了重写和重载的区别。这些内容对于理解C++的面向对象特性至关重要。
热门推荐
今年流行的穿法:“萝卜裤+马丁靴”,显腿长,小个子也能飒美
新手爸媽的全方位指南:如何選擇安心的新生兒洗沐產品?
春见与丑橘:果树种植中的两种佳品
袁绍的武将与战败:历史的反思
东莞理工学院:研究生一入学就进大厂、名企、科研机构!
千年翠影映齐鲁·古树群——宰相“刘罗锅”种板栗护河滩
三个就业场景,看长沙经济的活力与韧性
专利权利要求书怎么写
君山银针特级茶:岳阳特产价格与品鉴指南
三国杀规则全解析:从入门到不同局、血量及其他规则要点
49岁女性失眠的五大原因及应对方法
高尔夫:发力,以腰为源,用身体本能发力,不需要操控的打球
21三体患者能生育正常后代,这颠覆了我们对生殖隔离的认知
爵士乐旋律-聆听经典之音
历朝历代是如何解决宗室难养问题的?
期末评语如何写得出彩?这些方法老师们一定能用上
风湿病合并感染的护理
数据库如何存timestamp类型数据
快问快答:牙根短可以做矫正吗?正畸会导致牙根吸收吗?牙根短正畸一定会掉吗?
新手养猫,我还是建议养公猫!
异地婚姻怎么处理?从沟通到离婚的全方位指南
刚刚,江西籍院士获评“感动中国”年度人物!
《大学》中的“格物致知”:从古至今的知识获取之道
银川:挖掘再生水潜能,使利用率从1%提高到50%以上
攻略 | 盘点最具香港特色的地道美食!
血糖高的人能吃方便面吗?医生的专业解答来了
“云”端新趋势——超九成受访大学生使用数字资源助力学习和生活
荞麦饸饹面、菠菜饸饹面火爆配方解密
健康科普丨前置胎盘VS前壁胎盘,是一回事吗?
他时若遂凌云志,敢笑黄巢不丈夫!