2 zpcdcsdn zpcdcsdn 于 2016.01.13 11:31 提问

请教大家一个在虚析构函数存在时,C++虚函数表的问题

下面是在下的代码:

 #include <iostream>
using namespace std;

class Point
{
private:
    int X;
    int Y;
public:
    Point() {}
    Point(int x, int y) : X(x), Y(y) {}

    const int getX() { return X; }
    const int getY() { return Y; }
    virtual ~Point() {}
    virtual void printX() { cout << "X=" << X << endl; }
    virtual void printY() { cout << "Y=" << Y << endl; }

};

class Point3D :public Point
{
private:
    int Z;
public:
    Point3D()
        :Point()
    {}
    Point3D(int x, int y, int z)
        :Point(x, y), Z(z)
    {}
    const int getZ() { return Z; }
    virtual ~Point3D() {}
    virtual void printZ() { cout << "Z=" << Z << endl; }
    virtual void fun() { cout << "fun" << endl; }

};

int main()
{
    typedef void(*Funptr)();
    Point point(1, 2);
    Point3D point3D(1, 2, 3);
    Point3D* p3D = &point3D;
    void*** _p3D = (void***)&point3D;
    void** vfptr3D = *_p3D;
    int** ptr3D = (int**)vfptr3D;
    while (*ptr3D != NULL)
    {
        cout << *ptr3D << endl;
        ptr3D++;
    }
    cout << "--------------------------" << endl;
    Point* p = &point;
    void*** _p = (void***)&point;
    void** vfptr = *_p;
    int** ptr = (int**)vfptr;
    while (*ptr != NULL)
    {
        cout << *ptr << endl;
        ptr++;
    }
    return 0;
}

在上面的代码中,在下打印了派生类和基类的虚函数表,结果如下
图片说明
按理说,基类的虚函数表只有三项,分别对应~point(),printX(),printY(),如下图
图片说明
但大家也发现了,打印出的结果中最后多了一项!这是在VS2015下的结果,如果在codeblocks12.11下,连派生类的虚函数表最后也会多出一项,如下
图片说明
但是,只要去掉虚析构函数,就不会出现意料之外的多余项,可见出现多余项与类中含有虚析构函数有关,但在下又想不明白这是为什么,所以特向大家请教,希望各路大神能够不吝赐教,在下先行谢过!

3个回答

zpcdcsdn
zpcdcsdn   2016.01.13 19:35

图片说明
虽然这种事情可以不深究,但一想起来还是感到莫名其妙。我在有些资料上看到说虚函数表中不只有指向虚函数的指针,还有其它的东西,但究竟是什么,都没有明确说。

cuiwei1026522829
cuiwei1026522829   Ds   Rxr 2016.01.14 00:48

vs2013 和vs2015两个都装机器上,占地儿可不小。。

John_ToStr
John_ToStr   Rxr 2016.01.13 17:29

虚表是编译器相关的,vs2013根vs2015在处理虚表上有很大的区别。
下图是我在vs2013上面测的,跟你的理解是相符合的,你应该记住,对虚表的处理牵扯到时间空间效率的问题,随着编译器版本的改变。我觉得微软
是对虚表的处理改变了方法,并且提高了某种效率,或者是在二者之间取到了一个折衷。
图片说明

John_ToStr
John_ToStr 回复zpcdcsdn: 我说过了,是编译器的问题,虚表是运行时的,并且是编译器相关的...
2 年多之前 回复
zpcdcsdn
zpcdcsdn 非常感谢您的解答!其实之前我也在VS2013上测过,第一次运行结果是符合预期的,就像您上边的截图一样,但是,同样的程序。多次运行,就会出现和在VS2015上相似的结果。下面是我刚刚在VS2013上运行的结果截图。
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
虚函数,虚析构函数,虚函数表
转自http://hi.baidu.com/wangruiy01/blog/item/867552d0de8bdc339a502721.html 先看下面一段程序: #include using namespace std; class Person { public: virtual ~Person() //加了virtual,讲析构函数
c++虚析构函数在虚函数表中吗?
先放结论:在的!而且与声明的先后顺序有关为什么有这个疑问呢?因为析构函数的名字不一样啊......(好吧,是我too young了)实验代码的继承关系如下:class fa{ public: fa(){} virtual ~fa(){cout &amp;lt;&amp;lt; &quot;des fa&quot; &amp;lt;&amp;lt; endl;} virtual show(){cout &amp;lt;&amp;lt; ...
虚析构函数和虚函数表
在学习windows的时候,顺带复习下虚函数和虚函数表的知识 一、虚析构函数的必要性 我们常将一个基类的析构函数定义为虚函数,这样可以防止可能的内存泄漏,其中要点有以下几点: 1) 什么情况下会造成可能的内存泄漏?  当父类的析构函数不为虚函数,此时有一个父类的指针指向了子类对象,尝试释放掉这个指针所  占的内存,就可能造成内存的泄漏  我们先建两个类出来,其中myChild公有继承了
C++学习之多态篇(虚函数和虚析构函数的实现原理--虚函数表)
通过下面的代码来说明: #include #include #include using namespace std; /**  *  定义动物类:Animal  *  成员函数:eat()、move()  */ class Animal { public:     // 构造函数     Animal(){cout     // 析构函数    vi
【C/C++语法】C++ 虚函数表解析
文章源自:http://blog.csdn.net/haoel/article/details/1948051 (陈皓专栏) 与 http://blog.csdn.net/hairetz/article/details/4137000(hairetz的专栏) C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指
C++中虚析构函数的作用及其原理分析
参考http://blog.csdn.net/xiamentingtao/article/details/55517203 C++中的虚析构函数到底什么时候有用的,什么作用呢。 一.虚析构函数的作用 总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内
C++ 虚函数表 存在哪
C++通过虚函数实现多态。那么虚函数表具体保存在哪?是每一个对象都有虚函数表,还是每一类有虚函数表?让我们通过代码分析一下。
C++ 虚函数表 vfptr
前言大家都应该知道C++的精髓是虚函数吧? 虚函数带来的好处就是: 可以定义一个基类的指针, 其指向一个继承类, 当通过基类的指针去调用函数时, 可以在运行时决定该调用基类的函数还是继承类的函数. 虚函数是实现多态(动态绑定)/接口函数的基础. 可以说: 没有虚函数, C++将变得一无是处!既然是C++的精髓, 那么我们有必要了解一下她的实现方式吗? 有必要! 既然C++是从C语言的基础上发展而来的
C++中析构函数为虚函数时调用发生了什么变化
昨天去XX公司面试,面试官问了一个关于C++类析构函数为虚函数时,如果是父类的指针用子类来new,如果发生析构时,析构函数是virtual与不是virtual有什么区别。当时答的不好,回来总结了一下,在机器上实现了一遍,终于搞明白了。记录下来,以后遇到这种情况自己一定不要犯错了
虚指针存在证明及虚函数表
C++多态的实现原理是依赖虚指针来辨别具体使用家族类中的哪一个函数。以下就来证明虚指针的存在。 我们知道,指针的大小在一般情况下是4个字节,所以我们建立一个虚函数,再来计算该类的大小,便可以验证虚函数的存在。 代码如下:#include <iostream> using namespace std;class A { public: void print ()