关于C++多重继承的时候虚函数覆盖的问题
2015-06-14 13:42
501 查看
问题描述:
下面的代码试图去通过运行时程序分析和验证C++的虚表实现机制。
下面的代码在探究多重继承情况下,虚表的情况
copy代码, g++编译,观察输出结果,会发现,在派生类@Derived 中重新定义了虚函数 virtual void f(void)
这样以来,基类的函数实现就会被覆盖。通过虚表调用函数f,都会调用重新定义的这个,而不是旧的(实质是指针的覆盖)。
但是在我测试的时候出现了一个很奇葩的问题
观察输出,你会看到这里Derived::f()的函数实现的地址,居然有三个不同的地址,我都惊呆了。。。
理论上,实例化一个Derived::f()函数就可以了。把这个实例化的函数首地址指针覆盖到对应的虚表中即可。
但是这里居然出现了三个不同的Derived::f() (最起码看起来是不一样的。他们的地址不同额。。。)
表示很困惑。。。
![](https://img-blog.csdn.net/20150614133942472)
![](https://img-blog.csdn.net/20150614133832463)
为什么居然会有三个不同的Derived::f(),故意的嘛?
下面的代码试图去通过运行时程序分析和验证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; }
相关文章推荐
- C/C++中字符串的输入问题
- HDU-1049-Climbing Worm(C++ && 编程初学者的题......)
- 一步步将vim改造成C/C++开发环境(IDE)
- 【Search in Rotated Sorted Array II 】cpp
- C/C++中##与#的使用
- c语言中如何实现可变参数
- C语言中通过按位与求奇偶源码
- 【leetcode c++】14Longest Common Prefix
- _int64 C语言中怎么用
- C++ 虚析构函数 分析
- C/C++程序员面试易错题
- C++精确计算代码执行时间精度微秒级
- c++ 模板联系4
- c++ 模板联系4
- c++ 模板练习2
- C++ 一般模板友元关系
- C++ 一般模板友元关系
- c++ 模板练习2
- C++ 模板练习1
- C++ 模板练习1