关于C++多重继承的时候虚函数覆盖的问题

问题描述:

下面的代码试图去通过运行时程序分析和验证C++的虚表实现机制。

下面的代码在探究多重继承情况下,虚表的情况


copy代码, g++编译,观察输出结果,会发现,在派生类@Derived 中重新定义了虚函数 virtual void f(void)

这样以来,基类的函数实现就会被覆盖。通过虚表调用函数f,都会调用重新定义的这个,而不是旧的(实质是指针的覆盖)。


但是在我测试的时候出现了一个很奇葩的问题

观察输出,你会看到这里Derived::f()的函数实现的地址,居然有三个不同的地址,我都惊呆了。。。

理论上,实例化一个Derived::f()函数就可以了。把这个实例化的函数首地址指针覆盖到对应的虚表中即可。

但是这里居然出现了三个不同的Derived::f() (最起码看起来是不一样的。他们的地址不同额。。。)

表示很困惑。。。







为什么居然会有三个不同的Derived::f(),故意的嘛?


/*******************************************************************
Programmer  :   EOF
Date        :   2015.06.13
File        :   virtual_function_for_multiple_inheritance.cpp
E-mail      :   jasonleaster@gmail.com

 ******************************************************************/

#include <iostream>

using namespace std;

typedef  void (*FUN) (void);

class Base_1
{
    public:

        int num;

        Base_1():prv_data(100), num(100) { }

        virtual void f(void){ cout << " Base_1::f()" << endl; }
        virtual void g(void){ cout << " Base_1::g()" << endl; }
        virtual void h(void){ cout << " Base_1::h()" << endl; }

    private:
        /*
           Private  Data
         */
        int prv_data;

};

class Base_2
{
    public:

        int num;

        Base_2():prv_data(200), num(200) { }

        virtual void f(void){ cout << " Base_2::f()" << endl; }
        virtual void x(void){ cout << " Base_2::x()" << endl; }

    private:
        /*
           Private  Data
         */
        int prv_data;

};

class Base_3
{
    public:

        int num;

        Base_3():prv_data(300), num(300) { }

        virtual void g(void){ cout << " Base_3::g()" << endl; }

    private:
        /*
           Private  Data
         */
        int prv_data;

};

class Derived : public Base_3, public Base_2, public Base_1
{
    public:

        int num;

        Derived():num(42), prv_data(42) { }

        virtual void y(void){ cout << " Derived::y()" << endl; }

        /*
           Here we re-implement the virtual function @f().
           Compiler will rewrite the virtual table
         */
        virtual void f(void){ cout << " Derived::f()" << endl; }
        virtual void g(void){ cout << " Derived::g()" << endl; }


    private:
        int prv_data;
};

template<class T>
unsigned long* get_element(T &obj, int offset = 0, int vprt_offset = 0)
{
    return ((unsigned long*)*((unsigned long*)(&obj) + vprt_offset)) + offset ;
}

int main()
{
    Derived d;

    cout << "Virtual Table of @Base_3 and @Derived:" << endl;

    cout << (int*)*get_element(d, 0, 0) << endl;
    ((FUN)(*get_element(d, 0, 0))) ();

    cout << (int*)*get_element(d, 1, 0) << endl;
    ((FUN)(*get_element(d, 1, 0))) ();

    cout << (int*)*get_element(d, 2, 0) << endl;
    ((FUN)(*get_element(d, 2, 0))) ();


    cout << "Virtual Table of @Base_2:" << endl;

    cout << (int*)*get_element(d, 0, sizeof(Base_3)/8) << endl;
    ((FUN)(*get_element(d, 0, sizeof(Base_3)/8))) ();

    cout << (int*)*get_element(d, 1, sizeof(Base_3)/8) << endl;
    ((FUN)(*get_element(d, 1, sizeof(Base_3)/8))) ();


    cout << "Virtual Table of @Base_1:" << endl;
    cout << (int*)*get_element(d, 0, (sizeof(Base_3) + sizeof(Base_2))/8) << endl;
    ((FUN)(*get_element(d, 0, (sizeof(Base_3) + sizeof(Base_2))/8))) ();
  
    cout << (int*)*get_element(d, 1, (sizeof(Base_3) + sizeof(Base_2))/8) << endl;
    ((FUN)(*get_element(d, 1, (sizeof(Base_3) + sizeof(Base_2))/8))) ();

    cout << (int*)*get_element(d, 2, (sizeof(Base_3) + sizeof(Base_2))/8) << endl;
    ((FUN)(*get_element(d, 2, (sizeof(Base_3) + sizeof(Base_2))/8))) ();

    return 0;
}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值