虚表剖析
来源:互联网 发布:lstm python 编辑:程序博客网 时间:2024/04/29 01:10
虚表剖析
举例:
class Test{public:Test(){ _test = 10; cout << "this = " << this << endl;};virtual ~Test(){}private:int _test;}; int main(){Test t;cout << sizeof(Test) << endl;system("pause");return 0;};
当有虚函数时,编译器会生成一张虚表,在对象的前四个字节(虚表指针);
当有多个虚函数时,函数模型又是怎样呢?
上代码验证(没有重写):
在基类和派生类中分别添加虚函数
class CBase{public:CBase(){m_iTest = 10;}virtual void FunTest0(){cout<<"CBase::FunTest0()";}virtual void FunTest1(){cout<<"CBase::FunTest1()";}virtual void FunTest2(){cout<<"CBase::FunTest2()";}private:int m_iTest;};class CDerived:public CBase{public:virtual void FunTest4() {cout<<"CDerived::FunTest4()";} virtual void FunTest5(){cout<<"CDerived::FunTest5()";}virtual void FunTest6(){cout<<"CDerived::FunTest6()";}};typedef void (*FUN_TEST)();void FunTest(){CBase base;cout<< "CBase vfptr:"<<endl;for (int iIdx = 0; iIdx < 3; ++iIdx){FUN_TEST funTest = (FUN_TEST)(*((int*)*(int *)&base + iIdx));funTest();cout<< ": "<<(int *)funTest<<endl; }cout<<endl;CDerived derived;cout<< "CDerived vfptr:"<<endl;for (int iIdx = 0; iIdx < 6; ++iIdx){ FUN_TEST funTest = (FUN_TEST)(*((int*)*(int *)&derived + iIdx));funTest();cout<< ": "<<(int *)funTest<<endl;}}
运行结果:
结论:
1.虚函数按照声明顺序存放在虚表中,
2.在派生类中,先是基类的虚函数,后存放派生类的虚函数,
有重写
class CBase{public:virtual void FunTest0(){cout<<"CBase::FunTest0()"<<endl;}virtual void FunTest1(){cout<<"CBase::FunTest1()"<<endl;}virtual void FunTest2(){cout<<"CBase::FunTest2()"<<endl;}virtual void FunTest3(){cout<<"CBase::FunTest3()"<<endl;}};class CDerived:public CBase {public:virtual void FunTest0(){cout<<"CDerived::FunTest0()" <<endl;}virtual void FunTest1(){cout<<"CDerived::FunTest1()" <<endl;}virtual void FunTest4(){cout<<"CDerived::FunTest4()" <<endl;}virtual void FunTest5(){cout<<"CDerived::FunTest5()" <<endl;}};
1.在派生类中,先拷贝基类的虚函数表,如果重写了某个虚函数,就在对应位置换成重写后的虚函数,
2.接着跟上自己定义的虚函数,
ATTENTION:
CBase base;CDerived derived;pBase = &base;//指向基类,得到的是基类的虚表指针pBase->FunTest();pBase = &derived;//指向派生类,得到派生类的指针pBase->FunTest();CDerived* ptr = (CDerived*)&base;//派生类的指针指向基类地址ptr->FunTest();
通过基类的引用或指针调用虚函数时,要根据运行时指向的类型决定;
调用非虚函数时,无论基类指向何种类型,调用的都是基类的函数,
通过一个派生类类型的指针强制指向基类地址,调用非虚函数时是派生类的函数,调用虚函数时是调用基类中的。
多重继承:
上代码:
class CBase0{public:CBase0(){m_iTest = 0xB0;}virtual void PrintB0(){cout<<"m_iTest = "<<hex<<m_iTest<< " CBase0::PrintB0()" <<endl;}int m_iTest;};class CBase1{public:CBase1(){m_iTest = 0xB1;}virtual void PrintB1(){cout<<"m_iTest = "<<hex<<m_iTest<< " CBase1::PrintB1()" <<endl;}int m_iTest;};class CBase2{public:CBase2(){m_iTest = 0xB2;}virtual void PrintB2(){cout<<"m_iTest = "<<hex<<m_iTest<< " CBase2::PrintB2()" <<endl;}int m_iTest;};class CDerived:public CBase0, public CBase1, public CBase2{public:CDerived(){m_iTest = 0xD0;}virtual void PrintD(){cout<<"m_iTest = "<<hex<<m_iTest<< " CDerived::PrintD()"<<endl;}int m_iTest;};
数据模型:
CDerived 的虚函数表放在第一个继承基类的虚表后面;
当有虚函数覆盖时,每次调用的都是派生类中重写的;
0 0
- 虚函数表剖析
- 虚表剖析
- 虚表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- c++ 多态/虚表剖析
- C++虚函数表剖析
- 虚函数表深度剖析
- C++虚函数表剖析
- C++虚函数表深入剖析
- C++虚函数表深入剖析
- C++虚函数表深入剖析
- C++虚函数表深入剖析
- c++ 中多态总结以及虚表剖析
- tianxianpei
- 图解script的三种加载方式 异步加载顺序
- Docker内安装Flume
- 有限域的某一章节的某一小部分的简单证明
- 虚幻UE4中移动端水材质的设置
- 虚表剖析
- 02-python学习笔记:字典dict和集合set
- 商业数据库之死:Oracle 的困境
- spring中通过配置文件方式实现定时任务
- 个人模板 字符串最小表示法
- LeetCode Two Sum
- 解决 cannot find a valid baseurl for repo : base
- Eclipse在引入Maven工程后,找不到Maven Dependencies。使得代码报错,具体如下图所示: 而正常Maven的工程如下所示: 产生这种现象的原
- Python PIL解码JPEG文件失败