虛函數(shù) 純虛函數(shù) 虛類

虛函數(shù)

類的某些函數(shù),基類希望它的派生類各自定義這些函數(shù)各自的版本。
除了構(gòu)造函數(shù),任何函數(shù)都可以是虛函數(shù)。
讓派生類繼承借口和缺省定義(默認(rèn)定義)。

定義&聲明

class A
{
virtual int get(){};
};

class B:public A
{
int get() override
}

如果是普通的虛函數(shù)(不是純虛函數(shù)),那么基類也是需要提供虛函數(shù)的定義的。
因?yàn)椴皇羌兲摵瘮?shù),那么該類就可以實(shí)例化,那就必須需要定義。
派生類必須在其內(nèi)部重新定義的虛函數(shù)進(jìn)行聲明。

在基類中定義虛函數(shù)的時(shí)候需要在最開頭加virtual。

虛函數(shù)可以有默認(rèn)實(shí)參,且派生類也可以定義不同的默認(rèn)實(shí)參,但是最好相同。

重寫

在子類函數(shù)重寫的時(shí)候,可以選擇加也可以選擇不加virtual。同時(shí),如果可以在最結(jié)尾的時(shí)候加override確認(rèn)是重寫。
在派生類中覆蓋了某個(gè)虛函數(shù)時(shí),可以再一次使用virtual指出該函數(shù)的性質(zhì),也可以不加。但一個(gè)函數(shù)被聲明為虛函數(shù)時(shí),在他的所有派生類中,都是虛函數(shù)。
重寫時(shí),虛函數(shù)的返回值,形參必須完全相同。

但是,當(dāng)基類返回的是自己類型的指針時(shí)。那么氣派生類可以修改虛函數(shù)的返回值,但必須是返回派生類自身類型的指針。

另外,在分離定義的時(shí)候,不能加virtual.

關(guān)鍵字

override

使用override關(guān)鍵字,用來確認(rèn)定義的函數(shù)確實(shí)是覆蓋了基類的虛函數(shù),如果沒有覆蓋,那么編譯時(shí)候會(huì)報(bào)錯(cuò)。

使用

類的函數(shù)成員分類

  1. 普通函數(shù)成員:基類希望其派生類直接繼承,而不要改變的函數(shù)
  2. 虛函數(shù):基類希望其派生類進(jìn)行覆蓋的函數(shù)。

普通虛函數(shù),可以派生類可以不用重寫。
純虛函數(shù),必須重寫。

普通成員函數(shù),其解析過程發(fā)生在編譯時(shí)。
虛函數(shù)的解析可能在編譯時(shí),也可能是在運(yùn)行時(shí)。
當(dāng)通過指針或引用調(diào)用對(duì)象的虛函數(shù)時(shí)。那么函數(shù)會(huì)在運(yùn)行時(shí)才會(huì)被解析。

這里解析的含義是,當(dāng)對(duì)象調(diào)用自己的成員函數(shù)的時(shí)候,是執(zhí)行自己的成員函數(shù),還是執(zhí)行其子類的成員函數(shù)。
當(dāng)將一個(gè)派生類對(duì)象的指針或引用賦值給基類對(duì)象指針時(shí)(此時(shí)會(huì)發(fā)生派生類向基類的轉(zhuǎn)化),在運(yùn)行時(shí)解析。執(zhí)行的是派生類的成員函數(shù)。

如果我們想回避虛函數(shù)的動(dòng)態(tài)綁定機(jī)制,而直接運(yùn)行派生類基類的成員函數(shù)。(調(diào)用的函數(shù)仍然是一個(gè)虛函數(shù),只是我們希望調(diào)用基類的)。

pa->A::set();

顯式的指定。那么函數(shù)將在編譯時(shí)完成解析。

抽象基類

接口類

純虛函數(shù)

純虛函數(shù)的目的是為了讓派生類只繼承借口,不繼承定義。所以必須要定義。

定義

class A
{
virtual int get()=0;
};

=0只能在類內(nèi)出現(xiàn)。
同時(shí)仍然可以在類外提供這個(gè)函數(shù)的定義。唯一的調(diào)用方式是顯式調(diào)用。
出純虛函數(shù)可以不提供定義,因?yàn)檫@個(gè)類不能夠?qū)嵗?。但是可以定義指向這個(gè)類的指針。
同時(shí)這個(gè)類里面還是可以出現(xiàn)正常的虛函數(shù),成員變量。

構(gòu)造函數(shù)

派生類構(gòu)造函數(shù)只初始化他的直接基類。也就是說派生類在構(gòu)造函數(shù)中只能調(diào)用直接基類的構(gòu)造函數(shù),不能使用其間接基類的構(gòu)造函數(shù)。

class C:public B
{
public:
  C():B(),A()
  {
  };
}

這里報(bào)錯(cuò)

 type 'A' is not a direct base of 'C'
  C():B(),A(){};

虛析構(gòu)函數(shù)

任何函數(shù),只要帶有一個(gè)虛函數(shù),那么他的析構(gòu)函數(shù)必將是虛函數(shù)。

如果一個(gè)類的析構(gòu)函數(shù)不是虛函數(shù),那么不能將派生類向基類轉(zhuǎn)化

如果say()函數(shù)不是虛函數(shù)

//忽略大部分
A *pa;
B *pb;
pa=pb;

pa->say();

執(zhí)行的是類A的成員函數(shù)。

如果say()函數(shù)是虛函數(shù),那么執(zhí)行的是 類B的函數(shù)成員。

所以,如果基類的析構(gòu)函數(shù)不是虛函數(shù),那么我們使用上述的轉(zhuǎn)化的時(shí)候,析構(gòu)的將是類A的析構(gòu)函數(shù)。
那么其派生類部分的成員將無法析構(gòu)。

所以,析構(gòu)函數(shù)必須是虛函數(shù)。

析構(gòu)時(shí),從最外層向基層依次執(zhí)行析構(gòu)函數(shù).

構(gòu)造函數(shù)和析構(gòu)函數(shù)中不能使用虛函數(shù)

構(gòu)造函數(shù)中,構(gòu)造不完全,調(diào)用的是基類的函數(shù).
同樣析構(gòu)時(shí)也一樣。

對(duì)象構(gòu)造期間,虛函數(shù)不是虛函數(shù)。所以調(diào)用不會(huì)出錯(cuò),只是不知道會(huì)發(fā)生什么。
也就是說,派生類構(gòu)造時(shí),如果正處于基類構(gòu)造函數(shù)執(zhí)行期間,那么類型是基類類型,也就是說誰的構(gòu)造函數(shù)在執(zhí)行,那類型就是什么。
因?yàn)?,如果將基類函?shù)定義為虛函數(shù)。那么,無法初始化。編譯會(huì)報(bào)錯(cuò)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,680評(píng)論 1 51
  • C++文件 例:從文件income. in中讀入收入直到文件結(jié)束,并將收入和稅金輸出到文件tax. out。 檢查...
    SeanC52111閱讀 3,103評(píng)論 0 3
  • C++虛函數(shù) C++虛函數(shù)是多態(tài)性實(shí)現(xiàn)的重要方式,當(dāng)某個(gè)虛函數(shù)通過指針或者引用調(diào)用時(shí),編譯器產(chǎn)生的代碼直到運(yùn)行時(shí)才...
    小白將閱讀 1,803評(píng)論 4 19
  • 一個(gè)博客,這個(gè)博客記錄了他讀這本書的筆記,總結(jié)得不錯(cuò)?!渡疃忍剿鰿++對(duì)象模型》筆記匯總 1. C++對(duì)象模型與內(nèi)...
    Mr希靈閱讀 5,908評(píng)論 0 13
  • Today is the first day of school, and right now we’re jus...
    黯藍(lán)megumi是Amy閱讀 2,763評(píng)論 0 3

友情鏈接更多精彩內(nèi)容