码迷,mamicode.com
首页 > 编程语言 > 详细

C++虚函数和虚函数表

时间:2016-11-22 16:53:31      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:指针   tar   color   include   alt   决定   images   结束   字节   

前导

在上面的博文中描述了基类中存在虚函数时,基类和派生类中虚函数表的结构。

在派生类也定义了虚函数时,函数表又是怎样的结构呢?

先看下面的示例代码:

 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中虚函数和虚函数表如下:

技术分享

C++虚函数和虚函数表

标签:指针   tar   color   include   alt   决定   images   结束   字节   

原文地址:http://www.cnblogs.com/kohlrabi/p/6089148.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!