日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入浅出之虚函数原理篇(笔记三)

發(fā)布時(shí)間:2024/6/5 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入浅出之虚函数原理篇(笔记三) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上一節(jié),我們講到了虛函數(shù),那么你知道虛函數(shù)是如何做到多態(tài)的嗎?

虛函數(shù)是通過后期綁定,在執(zhí)行時(shí)間接通過一張?zhí)摵瘮?shù)表,間接調(diào)用欲綁定的函數(shù)。表中的每一個(gè)元素都指向虛函數(shù)的地址。當(dāng)然,編譯器也會(huì)為類增加一項(xiàng)成員變量,此成員變量是一個(gè)指向虛函數(shù)表的指針。可用圖解表示如下:

?

注意:

成員函數(shù)memfuc()經(jīng)過編譯之后,形成代碼,然后放在內(nèi)存中的代碼區(qū),并不是數(shù)據(jù)段。成員函數(shù)都是放在一起,而且由同一個(gè)類的所有對(duì)象共享。,用sizeof(a)計(jì)算的結(jié)果是不包括代碼段的。

以下幾點(diǎn),等下我們一一論證:

1.每一個(gè)由此類派生出來的對(duì)象,都有一個(gè)vptr。當(dāng)我們通過對(duì)象調(diào)用虛函數(shù)時(shí),實(shí)際上是通過vptr找到虛函數(shù)表,然后通過虛函數(shù)表找到真正的虛函數(shù)地址。

2.虛函數(shù)表中的內(nèi)容是根據(jù)類中的虛函數(shù)聲明順序一個(gè)一個(gè)填 入函數(shù)指針。

3.當(dāng)派生類繼承了基類后,同時(shí)也繼承了虛函數(shù)表,當(dāng)我們?cè)谂缮愔行薷牧颂摵瘮?shù)時(shí),其對(duì)應(yīng)的虛函數(shù)表中所指向的函數(shù)地址,就不再是基類的了,而是派生類的了。此點(diǎn)我們用圖解如下:

?

現(xiàn)在我們來分析一下到底是不是這樣的?這一節(jié)講解以下面的代碼為例(在上一節(jié)的例子基礎(chǔ)上修改而成)

?

Code
#include?<iostream.h>
#include?
<stdio.h>
#include?
<string.h>

class?CEmployee
{
public:
????
int?m_name;
public:
????CEmployee(){};
????
????
virtual?int?computerPay()
????{
????????printf(
"這是基類的計(jì)算方法");
????????
return(2);
????}
????
virtual?void?display()
????{
????????printf(
"職員");
????}

};

class?CWage:public?CEmployee
{
public:
????
int?m_wage;
????
int?m_hour;
public:
????CWage(){};

????
void?set(int?wage,int?hour)
????{
????????m_wage
=wage;
????????m_hour
=hour;
????}
????
virtual????int?computerPay()
????{
????????
return?m_wage*m_hour;
????}
????
virtual?void?display()
????{
????????printf(
"時(shí)薪職員");
????}
};

class?CSales:public?CWage
{
public:
????
int?n_sale;
????
int?n_hour;
public:
????CSales(){};
????
????
void?set(int?sale,int?hour)
????{
????????n_sale
=sale;
????????n_hour
=hour;
????}
????
virtual????int?computerPay()
????{
????????
return?n_sale*n_hour+CWage::computerPay();
????}
????
virtual?void?display()
????{
????????printf(
"銷售員");
????}

};

void?main()
{
????cout
<<sizeof(CEmployee)<<endl;
????cout
<<sizeof(CWage)<<endl;
????cout
<<sizeof(CSales)<<endl;
????CEmployee?a;
????CWage?????b;
????CSales????c;
????b.m_name
=1;
????b.m_wage
=2;
????b.m_hour
=3;
????cout
<<b.m_name<<endl;
????cout
<<b.m_wage<<endl;
????cout
<<b.m_hour<<endl;

????cout
<<&b<<endl;
????cout
<<&(b.m_name)<<endl;
????cout
<<&(b.m_wage)<<endl;
????cout
<<&(b.m_hour)<<endl;
????cout
<<&c<<endl;
}

運(yùn)行后的結(jié)果如下:

?

我們來分析一下:

1.sizeof(CEmployee)的大小為8,而這個(gè)類中只有一個(gè)整型是4個(gè)字節(jié),那么還有四個(gè)字節(jié)是誰占了呢,對(duì)了,就是指向虛函數(shù)表的vptr成員變量。說明確實(shí)在類中只要有虛函數(shù),就一定會(huì)有vptr這個(gè)成員變量。

2.sizeof(CWage)的大小為16,實(shí)際上是基類的整型+本類的兩個(gè)整型+從基類繼承的vptr也占用了四個(gè)字節(jié),剛好說明派生類繼承了虛函數(shù)表。

3.看清0x0012ff68這個(gè)內(nèi)存地址,它是類CWage對(duì)象的起始地址,這個(gè)地址中的內(nèi)容剛好是vptr,我們跟蹤程序,調(diào)試時(shí)可查,我把圖取上來大家看一下:

?

4.虛函數(shù)表中的內(nèi)容是根據(jù)類中的虛函數(shù)聲明順序一個(gè)一個(gè)填 入函數(shù)指針。大家看上圖先是壓入CWag::computerPay,然后再是CWage::display。

5.當(dāng)派生類繼承了基類后,同時(shí)也繼承了虛函數(shù)表,當(dāng)我們?cè)谂缮愔行薷牧颂摵瘮?shù)時(shí),其對(duì)應(yīng)的虛函數(shù)表中所指向的函數(shù)地址,就不再是基類的了,而是派生類的了。現(xiàn)在我們看到的是b對(duì)象(即CWage),轉(zhuǎn)到C對(duì)象時(shí),會(huì)發(fā)現(xiàn)虛函數(shù)表中的地址都發(fā)生變化了。

今天就先寫到這兒,本人才shu學(xué)淺,有什么意見或見意,希望能與大家一同探討。

?

轉(zhuǎn)載于:https://www.cnblogs.com/chuncn/archive/2009/02/27/1399901.html

總結(jié)

以上是生活随笔為你收集整理的深入浅出之虚函数原理篇(笔记三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。