深入解析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++的面向对象特性至关重要。
热门推荐
《第七史诗》隐藏曲目解锁攻略:第七章隐藏曲解锁详细步骤
什么是震荡指标?震荡指标在投资中的应用策略有哪些?
哪三种症状可以服用连花清瘟?中医教你用连花清瘟防疫
何小鹏:互联网到新能源车的跨界传奇
新《公司法》下股东知情权诉讼主体资格详解
隐名股东显名公司法解释三:揭示股东身份,维护公司权益
用魔芋干粉做魔芋豆腐
施工组织计划到底应该怎么做?
如何确保吉祥物设计理念与品牌形象相匹配?
实验三十 验证动量定理(恒力)
格拉斯哥美术学院交互设计课程详解:本科与硕士课程对比
磨刀技巧全攻略:让你的刀具焕发新生与锋利魅力
手术后疼痛吃什么止疼药
营业执照注销指南:所需材料与流程详解
买房契税能否退税?法律依据与实际操作解析
北斗卫星导航系统:开创智慧交通时代
北斗卫星通讯终端是什么?有什么功能?
早读丨《道德经》10种人生智慧,受用一生
发展北斗的意义是什么?北斗系统的应用场景有哪些?
新版生产安全事故应急预案
五一出境游十大热门目的地 五一适合出国旅游的10个国家
高血压症状的早期表现
工伤认定与处理流程:保障劳动者权益的法律指南
艾灸拔罐操作流程
五首诗词,喜迎春分:东风吹散梨花雨,醉卧青山白云边
我国多个地区实行无彩礼政策,婚礼费用由双方共同承担
结婚份子钱多 日本年轻人压力大
怎么确认存货?怎样准确确认存货并评估其价值?
菩提祖师 vs. 唐僧:悟空的成长秘笈
出口单证工作的操作流程