【C++深度探索】全面解析多态性机制(二)
🔥 个人主页:大耳朵土土垚
🔥 所属专栏:C++从入门至进阶
这里将会不定期更新有关C/C++的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉
VPS购买请点击我 前言
我们知道C++多态实现有两个条件——一是基类的指针或引用调用虚函数,另一个是基类中有虚函数并且在派生类中实现虚函数重写;这两个条件缺一不可,这与多态实现的底层原理有关,今天我们就来学习一下多态实现的原理🥳🥳
目录
- 前言
- 1.虚函数表
- 2.派生类中的虚表
- 情况一:只有基类有虚函数,派生类没有
- 情况二:基类和派生类中都有虚函数,并且虚函数没有被重写
- 情况三:基类中定义虚函数,并且派生类中对该虚函数进行了重写
- 综合这三种情况
- 3.多态原理
- 动态绑定与静态绑定
- 4.多继承中的虚函数表
- 5.结语
1.虚函数表
虚函数表(Virtual Function Table,VTable)是C++中实现动态多态性的一种机制。每个包含虚函数的类都有一个对应的虚函数表,用于存储该类的虚函数地址。
虚函数表是一个包含函数指针的数组,每个函数指针指向相应虚函数的实现。
也就是说在类中定义了虚函数,那么该类就会包含一个虚函数表来存放虚函数的函数指针,注意这里是指类中会存储虚函数表的指针来达到效果,因为如果虚函数很多,直接存储虚函数表可能会占用很多空间。
例如:
class Base { public: virtual void Func1() { cout cout private: int _b = 1; }; class Derive :public Base { public: virtual void Func2() { cout Derive d; return 0; } public: virtual void Func1() { cout private: int _d = 2; }; int main() { Derive d; return 0; } public: virtual void Func1() { cout public: virtual void Func2() { cout Derive d; return 0; } // 依次取虚表中的虚函数指针打印并调用。调用就可以看出存的是哪个函数 cout printf(" 第%d个虚函数地址 :0X%x-", i, vTable[i]); VFPTR f = vTable[i]; f();//调用该函数 } cout Base b; Derive d; //打印b对象中虚函数的地址 VFPTR* vTableb = (VFPTR*)(*(int*)&b); PrintVTable(vTableb); //打印d对象中虚函数的地址 VFPTR* vTabled = (VFPTR*)(*(int*)&d); PrintVTable(vTabled); } public: virtual void Func1() { cout public: virtual void Func1()//重写虚函数Fun1() { cout Base b; Derive d; return 0; } public: virtual void Func1() { cout cout cout public: virtual void Func1()//重写 { cout Base b; Derive d; } int i = 0; static int j = 1; int* p1 = new int; const char* p2 = "aaaaa"; Base b; Derive d; printf("栈:%p\n", &i); printf("静态区:%p\n", &j); printf("堆:%p\n", p1); printf("常量区:%p\n", p2); printf("Base虚表地址:%p\n", *(int*)&b); printf("Derive虚表地址:%p\n", *(int*)&d); return 0; } public: virtual void BuyTicket() { cout public: virtual void BuyTicket() { cout p.BuyTicket(); } int main() { Person Black; Func(Black); Student tutu; Func(tutu); return 0; } public: virtual void func1() { cout cout public: virtual void func1() { cout cout public: virtual void func1() { cout cout cout printf(" 第%d个虚函数地址 :0X%x,-", i, vTable[i]); VFPTR f = vTable[i]; f(); } cout Derive d; //第一个虚表地址 VFPTR* vTableb1 = (VFPTR*)(*(int*)&d); PrintVTable(vTableb1); //找到第二个虚表的地址 VFPTR* vTableb2 = (VFPTR*)(*(int*)((char*)&d + sizeof(Base1))); PrintVTable(vTableb2); return 0; }
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。