读C++虚函数表及C++对象的内存布局笔记
2013-05-15 19:07
288 查看
C++虚函数表解析:http://blog.csdn.net/haoel/article/details/1948051
C++对象的内存布局(上):http://blog.csdn.net/haoel/article/details/3081328
C++对象的内存布局(下):http://blog.csdn.net/haoel/article/details/3081385
C++虚函数表解析
1.一般继承(无虚函数覆盖
虚函数按照其声明顺序存放于表中。
父类的虚函数在子类的虚函数前面
2.一般继承(有虚函数覆盖)
覆盖的f()函数被放到了虚表中原来父类虚函数的位置。
没有被覆盖的函数依旧。
3.多重继承(无虚函数覆盖)(针对子类实例中的虚函数表)
每个父类都有自己的虚表。
子类的成员函数被放到了第一个父类的表中。(所谓的第一个父类是按照声明的顺序来判断的)。
4.多重继承(有虚函数覆盖)(针对子类实例中的虚函数表)
覆盖的f()函数被放到了每个虚表中原来父类虚函数的位置。
5.安全性
通过父类型的指针访问子类自己的虚函数
访问non-public的虚函数
C++对象的内存布局(上)
1.对象的影响因素
成员变量
虚函数(产生虚函数表)
单一继承(只继承于一个类)
多重继承(继承多个类)
重复继承(继承多个父类中其父类有相同的超类)
虚拟继承(使用Virtual方式继承,为了保证继承后父类的内存布局只会存在一份)
2.单一的一般继承
虚函数表在最前面的位置
成员变量根据其继承和声明顺序依次放在后面。
在单一的继承中,被overwrite的虚函数在虚函数表中得到了更新。
3.多重继承
每个父类都有自己的虚函数表。
子类的虚成员函数被放到了第一个父类的表中。
内存布局中,其父类布局依次按声明的顺序排列。
每个父类的虚表中的f()函数都被overwrite成了子类的f()。这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。
C++对象的内存布局(上):http://blog.csdn.net/haoel/article/details/3081328
C++对象的内存布局(下):http://blog.csdn.net/haoel/article/details/3081385
C++虚函数表解析
1.一般继承(无虚函数覆盖
虚函数按照其声明顺序存放于表中。
父类的虚函数在子类的虚函数前面
2.一般继承(有虚函数覆盖)
覆盖的f()函数被放到了虚表中原来父类虚函数的位置。
没有被覆盖的函数依旧。
//涵盖上面两点的例子 #include <iostream> using namespace std; class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout << "Base::g" << endl; } virtual void h() { cout << "Base::h" << endl; } }; class Derived:public Base{ public: void f(){ cout << "Derived::f" << endl;} virtual void f1() { cout << "Derived::f1" << endl;} virtual void g1() { cout << "Derived::g1" << endl;} virtual void h1() { cout << "Derived::h1" << endl;} }; int main(void) { typedef void(*Fun)(void); Base *b; Base B; Derived D; b = &D; Fun pFun = NULL; cout << "虚函数表地址:" << (int*)(b) << endl; cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(b) << endl; // Invoke the first virtual function pFun = (Fun)*((int*)*(int*)(b)); pFun(); pFun = (Fun)*((int*)*(int*)(b)+1); pFun(); pFun = (Fun)*((int*)*(int*)(b)+2); pFun(); pFun = (Fun)*((int*)*(int*)(b)+3); pFun(); pFun = (Fun)*((int*)*(int*)(b)+4); pFun(); pFun = (Fun)*((int*)*(int*)(b)+5); pFun(); cout << (Fun)*((int*)*(int*)(b)+6) << endl; }
输出 虚函数表地址:0xbfcdefcc 虚函数表 — 第一个函数地址:0x8048fa8 Derived::f Base::g Base::h Derived::f1 Derived::g1 Derived::h1 1//为何是1而不是0。。。在“C++虚函数表解析”中附录二的例程中最后一个是0.
3.多重继承(无虚函数覆盖)(针对子类实例中的虚函数表)
每个父类都有自己的虚表。
子类的成员函数被放到了第一个父类的表中。(所谓的第一个父类是按照声明的顺序来判断的)。
4.多重继承(有虚函数覆盖)(针对子类实例中的虚函数表)
覆盖的f()函数被放到了每个虚表中原来父类虚函数的位置。
5.安全性
通过父类型的指针访问子类自己的虚函数
访问non-public的虚函数
C++对象的内存布局(上)
1.对象的影响因素
成员变量
虚函数(产生虚函数表)
单一继承(只继承于一个类)
多重继承(继承多个类)
重复继承(继承多个父类中其父类有相同的超类)
虚拟继承(使用Virtual方式继承,为了保证继承后父类的内存布局只会存在一份)
2.单一的一般继承
虚函数表在最前面的位置
成员变量根据其继承和声明顺序依次放在后面。
在单一的继承中,被overwrite的虚函数在虚函数表中得到了更新。
3.多重继承
每个父类都有自己的虚函数表。
子类的虚成员函数被放到了第一个父类的表中。
内存布局中,其父类布局依次按声明的顺序排列。
每个父类的虚表中的f()函数都被overwrite成了子类的f()。这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。
相关文章推荐
- c++笔记 虚函数表内存布局
- C++ 虚函数内存布局学习笔记
- C++对象模型笔记:对象实例内存布局的小小结
- C++对象的内存布局以及虚函数表和虚基表
- c++单继承、多继承、菱形继承的内存布局(虚函数表结构)
- C++对象的内存布局1---基础篇----C++ 虚函数表解析
- C++ 虚函数内存布局学习笔记
- 陈皓-C++ 对象的内存布局(上):笔记
- 【C++】c++单继承、多继承、菱形继承内存布局(虚函数表结构)
- c++单继承、多继承、菱形继承内存布局(虚函数表结构)
- C++对象的内存布局1---基础篇----C++ 虚函数表解析
- C++对象模型笔记:对象的三种内存布局
- C++对象模型-简述c++对象的内存布局
- C++ 虚函数内存布局学习笔记
- C++ 虚函数内存布局学习笔记
- C++对象模型笔记:对象的三种内存布局
- C++对象模型之详述C++对象的内存布局
- C++对象模型之详述C++对象的内存布局
- C++对象模型之详述C++对象的内存布局
- C++对象内存布局--①测试虚函数表属于类