C++虚函数表解析(高级篇)

原文: http://blog.csdn.net/haoel
一、前言
在《 C++虚函数表解析》中,对C++虚函数表进行了探讨,但是在谈论虚函数表里,至少有以下这些内容没有涉及:
1)有成员变量的情况。
2)有重复继承的情况。
3)有虚拟继承的情况。
4)有钻石型虚拟继承的情况。
 这篇文章将会是《 C++虚函数表解析》的一个续篇,将以C++对象的内存布局为重点,也是一篇高级进阶的文章。大家在读这篇文章之前对C++有一定的基础和了解,并能先读《 C++虚函数表解析》。
二、对象内存布局的影响因素
 对象内存布局的影响因素主要有以下几项:
 1 )成员变量
2)虚函数(产生虚函数表)
3)单一继承(只继承于一个类)
4)多重继承(继承多个类)
5)重复继承(继承的多个父类中其父类有相同的超类)
6)虚拟继承(使用virtual方式继承,为了保证继承后父类的内存布局只会存在一份)
上述的东西通常是C++这门语言在语义方面对对象内部的影响因素,当然,还会有编译器的影响(比如优化),还有字节对齐的影响。在这里我们都不讨论,我们只讨论C++语言上的影响。
 本篇文章着重讨论下述几个情况下的C++对象的内存布局情况。
  1)单一的一般继承(带成员变量、虚函数、虚函数覆盖)
2)单一的虚拟继承(带成员变量、虚函数、虚函数覆盖)
3)多重继承(带成员变量、虚函数、虚函数覆盖)
4)重复多重继承(带成员变量、虚函数、虚函数覆盖)
5)钻石型的虚拟多重继承(带成员变量、虚函数、虚函数覆盖)
 三、虚函数表复习
 我们简单地复习一下,我们可以通过对象的地址来取得虚函数表的地址,如:
 
    

            typedef void (* Fun )( void );
              Base b ;
              Fun pFun = NULL ;
              cout << "虚函数表地址:" << ( int *)(& b ) << endl ;
            cout << "虚函数表 — 第一个函数地址:" << ( int *)*( int *)(& b ) << endl ;
              // Invoke the first virtual function 
            pFun = (Fun)*((int*)*(int*)(&b));
            pFun();

我们同样可以用这种方式来取得整个对象实例的内存布局。因为这些东西在内存中都是连续分布的,我们只需要使用适当的地址偏移量,我们就可以获得整个内存对象的布局。
 本篇文章中的例程或内存布局主要使用如下编译器和系统:
1)Windows XP 和 VC++ 2003
2)Cygwin 和 G++ 3.4.4
四、深入C++对象的内存布局
单继承
关于单继承C++对象的内存布局请阅读《 C++ 对象的内存布局(单继承)》和《 C++虚函数表解析(基础篇)》
多重继承
关于多重继承C++对象的内存布局请阅读《 C++ 对象的内存布局(多重虚拟继承)》和《 C++虚函数表解析(基础篇)》
重复非虚拟继承
关于重复继承C++对象的内存布局请阅读《 C++ 对象的内存布局(重复非虚拟继承)》
重复虚拟继承
关于多重虚拟继承C++对象的内存布局请阅读《 C++ 对象的内存布局(重复虚拟继承)》

你可能感兴趣的:(C和C++语言)