C++多重继承虚函数表结构
在网上看到陈皓写的一篇关于虚函数表的解析的博客,讲的很好,但是关于多重继承那一块不是很理解。
先看下列代码:
#include <iostream>
using namespace std;
class Base1 {
public:
//虚函数定义
virtual void f() { cout << "Base1::f" << endl; }
virtual void g() { cout << "Base1::g" << endl; }
virtual void h() { cout << "Base1::h" << endl; }
};
class Base2 {
public:
//虚函数定义
virtual void f() { cout << "Base2::f" << endl; }
virtual void g() { cout << "Base2::g" << endl; }
virtual void h() { cout << "Base2::h" << endl; }
};
class Base3 {
public:
//虚函数定义
virtual void f() { cout << "Base3::f" << endl; }
virtual void g() { cout << "Base3::g" << endl; }
virtual void h() { cout << "Base3::h" << endl; }
};
//多继承时的情况---无虚函数覆盖
class DerivedMulti:public Base1,public Base2,public Base3{
public:
//虚函数定义
virtual void f1() { cout << "DerivedMulti::f1" << endl; }
virtual void g1() { cout << "DerivedMulti::g1" << endl; }
};
int main()
{
typedef void(*Fun)(void);
cout << "多重继承时的情况(无虚函数覆盖):" << endl;
DerivedMulti dMultiObj;
cout << "DerivedMulti类第一个虚函数表地址:" << (int*)(&dMultiObj) << endl;
cout << "依次调用三个虚函数表中的虚函数:" << endl;
cout << "第一个虚函数表中的虚函数:" << endl;
Fun pFun = NULL;
pFun = (Fun)*((int *)*((int*)(&dMultiObj)));
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 1);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 2);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 3);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 4);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 5);
pFun();
cout << "第二个虚函数表中的虚函数:" << endl;
pFun = (Fun)*((int *)*((int*)(&dMultiObj + 1)));
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj + 1)) + 1);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj + 1)) + 2);
pFun();
cout << "第三个虚函数表中的虚函数:" << endl;
pFun = (Fun)*((int *)*((int*)(&dMultiObj + 2)));
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj + 2)) + 1);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj + 2)) + 2);
pFun();
return 0;
}
上述代码是关于多重继承无虚函数覆盖时的情况,按照博客上所说的,子类虚函数表的结构应该如下所示:
但是我在代码中依次访问各个虚函数表中出现的虚函数时,运行到第二个虚函数表时程序就异常终止了:
谁能帮忙看看是什么原因?
运行环境是:Codeblocks 10.05(GCC)
依尔sama
11 years, 7 months ago
Answers
修改了你的代码,下面这样才是正确的
int main()
{
typedef void(*Fun)(void);
cout << "多重继承时的情况(无虚函数覆盖):" << endl;
DerivedMulti dMultiObj;
cout << "DerivedMulti类第一个虚函数表地址:" << (int*)(&dMultiObj) << endl;
cout << "依次调用三个虚函数表中的虚函数:" << endl;
cout << "第一个虚函数表中的虚函数:" << endl;
Fun pFun = NULL;
pFun = (Fun)*((int *)*((int*)(&dMultiObj)));
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 1);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 2);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 3);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)) + 4);
pFun();
cout << "第二个虚函数表中的虚函数:" << endl;
pFun = (Fun)*((int *)*((int*)(&dMultiObj)+ 1));
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)+ 1) + 1);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj)+ 1) + 2);
pFun();
cout << "第三个虚函数表中的虚函数:" << endl;
pFun = (Fun)*((int *)*((int*)(&dMultiObj )+ 2));
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj )+ 2) + 1);
pFun();
pFun = (Fun)*((int *)*((int*)(&dMultiObj )+ 2) + 2);
pFun();
return 0;
}
pFun = (Fun)
((int *)
((int
)(&dMultiObj)) + 5); //这里已经越界了,错误。
pFun = (Fun)
((int
)
((int
)(&dMultiObj + 1))); //这里错误,指针越界了。
(&dMultiObj + 1) 这里的指针运算是DerivedMulti
的指针运算,地址是0x22ff1c;指向下一个DerivedMulti了。
改为((int*)(&dMultiObj)+ 1) 这样才是指向下一个虚函数指针vptr。
看一下DerivedMulti 的内存布局图就清楚了。
Alamith
answered 11 years, 7 months ago