虚函数的机制

虚函数在类中的体现

对象的多态性需要通过虚表和虚表指针来完成,虚表指针被定义在对象首地址的前4字节处,因此虚函数必须作为成员函数使用。 
由于非成员函数没有 this 指针,因此无法获得虚表指针,进而无法获取虚表,也就无法访问虚函数。

子类对虚函数进行了重写,所以如果是子类的指针,是访问不到父类的成员函数的。而父类的指针可以访问到子类的成员函数。

值得注意的是,虽然虚表是共享的,但是虚表指针并不是,类的每一个对象有一个属于它自己的虚表指针。

编译环境:VS2012

  • 类中只有普通成员函数:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">class CClassA
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}
};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

类大小图1

  • 类中含有虚函数:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">class CClassA
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}
};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

类大小图2

由此可见,有虚函数的多了4个字节,这4个字节就是分给虚函数指针的.


虚函数表的存储机制

一般继承(无虚函数覆盖)

C++代码:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> namespace std;
class CClassA
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_b(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_c(){}
};
class CClassB : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> CClassA
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_e</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_f(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_g(){}
};
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main()
{
    CClassA objA;
    CClassB objB;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li></ul>

反汇编代码:

  • CClassB 的虚函数表
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassB@@6B@ DD FLAT:??_</span>R4CClassB@@6B@      ; CClassB::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_a@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_b@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_c@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_e@CClassB@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_f@CClassB@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_g@CClassB@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
  • CClassA 的虚函数表
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassA@@6B@ DD FLAT:??_</span>R4CClassA@@6B@      ; CClassA::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_a@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_b@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_c@CClassA@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

可以看到,虚函数表存放在常量段里(模块的数据段通常存放该模块的全局数据和静态数据,这样我们可以把虚表看作是模块的全局数据或者静态数据),并且 CClassB 继承 CClassA 后,虚函数表中的函数排列顺序为先基类再子类。

也可以在内存中证明排列顺序,如图: 
objB 的前三个是 objA 的三个函数

objB-objA

可得objB 的虚函数结构为: 
objB 的虚函数结构


一般继承(有虚函数覆盖)

C++代码:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">class CClassA
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_b(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_c(){}
};
class CClassB : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> CClassA
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//覆盖基类的fun_a</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_f(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_g(){}
};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

汇编中的虚函数表:

  • CClassB: (这里 fun_a 已经不再是 CClassA 的了)
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassB@@6B@ DD FLAT:??_</span>R4CClassB@@6B@      ; CClassB::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_a@CClassB@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_b@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_c@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_f@CClassB@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_g@CClassB@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
  • CClassA:
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassA@@6B@ DD FLAT:??_</span>R4CClassA@@6B@      ; CClassA::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_a@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_b@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_c@CClassA@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

在内存中的情况: 
第一个函数已经不同,说明基类中的被覆盖

这里写图片描述

objB 的虚函数结构为:

这里写图片描述


多重继承(无虚函数覆盖)

C++代码:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">class CClassA
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_b(){}
};
class CClassB 
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_c</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_d(){}
};
class CClassC : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> CClassA, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> CClassB
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    /*<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_c(){}*/
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_e(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_f(){}
};
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main()
{
    CClassA objA;
    CClassB objB;
    CClassC objC;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li></ul>

反汇编各个类的虚函数表:

  • CLassC (有两个虚函数表): 
    可以看到 C 本身 的虚函数被接在第一个继承类 CClassA 的后面
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassC@@6BCClassB@@@ DD FLAT:??_</span>R4CClassC@@6BCClassB@@@ ; CClassC::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_c@CClassB@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_d@CClassB@@UAEXXZ</span>
CONST   ENDS
CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassC@@6BCClassA@@@ DD FLAT:??_</span>R4CClassC@@6BCClassA@@@ ; CClassC::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_a@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_b@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_e@CClassC@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_f@CClassC@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>
  • CClassB :
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassB@@6B@ DD FLAT:??_</span>R4CClassB@@6B@      ; CClassB::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_c@CClassB@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_d@CClassB@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
  • CClassA :
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassA@@6B@ DD FLAT:??_</span>R4CClassA@@6B@      ; CClassA::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_a@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_b@CClassA@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

在内存中查看: 
objC 的总体情况(两个虚函数指针 vfptr):

这里写图片描述

  • objC 的内存:

这里写图片描述

第一个虚函数表指针 0036CD58H:

这里写图片描述

其中4个地址的内容分别是:(这里也可以看出 C 的虚函数跟在 A 的后面)

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

第二个虚函数表指针 0036CD74H:

这里写图片描述

其中2个地址的内容分别是:(这里就是第二个继承类的虚函数)

这里写图片描述

这里写图片描述

SO , CClassC 的虚表结构:

这里写图片描述


多重继承(有虚函数覆盖)

C++代码:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">class CClassA
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_b(){}
};
class CClassB 
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_c</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_d(){}
};
class CClassC : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> CClassA, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> CClassB
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fun_a</span>(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_c(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_e(){}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">virtual</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> fun_f(){}
};

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main()
{
    CClassA objA;
    CClassB objB;
    CClassC objC;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li></ul>

反汇编虚函数表:

  • CClassC:
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassC@@6BCClassB@@@ DD FLAT:??_</span>R4CClassC@@6BCClassB@@@ ; CClassC::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_c@CClassC@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_d@CClassB@@UAEXXZ</span>
CONST   ENDS

CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassC@@6BCClassA@@@ DD FLAT:??_</span>R4CClassC@@6BCClassA@@@ ; CClassC::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_a@CClassC@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_b@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_e@CClassC@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_f@CClassC@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>
  • CClassB:
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassB@@6B@ DD FLAT:??_</span>R4CClassB@@6B@      ; CClassB::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_c@CClassB@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_d@CClassB@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
  • CClassA:
<code class="hljs asciidoc has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">CONST   SEGMENT
??<span class="hljs-emphasis" style="box-sizing: border-box;">_7CClassA@@6B@ DD FLAT:??_</span>R4CClassA@@6B@      ; CClassA::<span class="hljs-smartquote" style="box-sizing: border-box;">`vftable'</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_a@CClassA@@UAEXXZ</span>
<span class="hljs-code" style="box-sizing: border-box;">    DD  FLAT:?fun_b@CClassA@@UAEXXZ</span>
CONST   ENDS</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

在内存中查看: 
objC 的内存:

这里写图片描述

第一个虚表:

这里写图片描述

对应的函数:

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

第二个虚表内容:

这里写图片描述

对应的函数:

这里写图片描述

这里写图片描述

SO , CClassC 的虚表结构:

这里写图片描述

值得注意的是,如果基类中有数据成员被继承,那么 CClassC 的对象的模型应该是这样的:

这里写图片描述

转载自:http://blog.csdn.net/hwithk/article/details/47976571

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值