在上面的博文中描述了基类中存在虚函数时,基类和派生类中虚函数表的结构。
在派生类也定义了虚函数时,函数表又是怎样的结构呢?
先看下面的示例代码:
1 #include <iostream> 2 3 using namespace std; 4 5 class A 6 { 7 public: 8 virtual void funcA(){ cout<<"A"<<endl; } 9 }; 10 11 class B 12 { 13 public: 14 virtual void funcB(){ cout<<"B"<<endl; } 15 }; 16 17 class C : public A, public B 18 { 19 public: 20 virtual void funcC(){ cout<<"C"<<endl; } 21 }; 22 23 int main() 24 { 25 C c; 26 cin.get(); 27 }
class A 和 class B 都有一个虚函数,然后 class C 继承 A 和 B。在VS2010中,查看变量:
如图所示,局部变量中只显示了从 A 和 B 继承来的虚函数表地址。那么 C 自己的虚函数呢?
首先查看 A 虚函数表地址:
可以看到,虚函数表中的前4个字节就是 A 中虚函数的地址(红色框)。同时后面又紧跟着4个有内容的字节,然后才是表示虚函数表结束的4个0。
可以猜测,这应该就是 C 的虚函数地址。再来看一下 B 的虚函数表:
可以看到,虚函数表中只有 B 的虚函数这一个地址。为了证实上面的猜测,将函数指针从 A::funcA 向后递增一次,应该就是对 C::funC的调用:
int main() { typedef void(*pfun)(); C c; auto p = &c; auto funcA = (pfun)**((int**)p); funcA(); // 调用 A::funcA auto funcC = (pfun)*(*((int**)p) + 1); funcC(); // 调用 C::funcC cin.get(); }
输出结果: 证实了我们的猜测。
如果在增加一个 class D 继承 C 呢?
class D : public C { virtual void funcD() {} }; int main() { D d; cin.get(); }
变量:
和 C 中展示的一样,只有两个虚函数表。
内存:
可以看到,在 A::funcA 后还有两个地址,可以推测就是 C::funcC 和 D::funcD 的地址了。
总结:
1、在多继承中,派生类的虚函数表的个数由它所继承的“顶层的”基类的个数决定:有多少个这样的基类,就有多少个虚函数表。
2、派生类自己的虚函数被追加到第一个虚函数表的后面。
例如下面的继承:
假设每个类 X 都有一个 funcX 虚函数,那么G中虚函数和虚函数表如下:
时间: 2024-10-26 14:56:12