什么叫多態(tài)性兼贸?
A:同樣的消息被不同類型的對象接收時,對象會采用完全不同的行為處理消息吃溅。
void play(HeroFighter *hf,EnemyFighter *ef){
if (hf->power() > ef->attack())//hf->power()調(diào)用會發(fā)生多態(tài)
cout<<"英雄勝"<<endl;
else
cout<<"英雄負"<<endl;
}
void main(int argc, char const *argv[])
{
HeroFighter hf;
AdvHeroFighter ahf;
EnemyFighter ef;
play(&hf,&ef);
play(&ahf,&ef);
}
多態(tài)性有幾種溶诞?
A:靜態(tài)多態(tài)性(函數(shù)重載、運算符重載等)動態(tài)多態(tài)性(虛函數(shù))决侈。
什么是虛函數(shù)螺垢?
A:允許派生類重新定義與基類同名的函數(shù),并且可以通過基類指針或引用來訪問基類或派生類的同名函數(shù)赖歌。
當基類的成員函數(shù)被聲明為虛函數(shù)枉圃,那么子類的同名函數(shù)會是虛函數(shù)嗎
A:是滴,所以此時在聲明子類的虛函數(shù)不需要用vritual關(guān)鍵字庐冯,如果子類沒有對基類的虛函數(shù)進行重新定義孽亲,那么子類會直接繼承基類的虛函數(shù)
如何定義虛函數(shù)?
A:虛函數(shù)的函數(shù)名展父、參數(shù)列表必須相同墨林,返回值大多時候相同(特例:若基類返回值為該類的指針或引用赁酝,子類返回值為子類的指針或引用,那么此時系統(tǒng)會認為它們是同名虛函數(shù))
虛函數(shù)的訪問修飾符的界定
A:當基類的虛函數(shù)的訪問修飾符為public時旭等,無論子類的虛函數(shù)的訪問修飾符是什么,都可以通過基類的指針或引用為所有派生類調(diào)用函數(shù)衡载。
什么是純虛函數(shù)搔耕?
A:基類中虛函數(shù)只有聲明沒有實現(xiàn)體
virtual double Area() const=0;
什么是抽象類
A:含有純虛函數(shù)的類為抽象類,如果基類定義多個純虛函數(shù)痰娱,子類沒有一一將純虛函數(shù)實現(xiàn)弃榨,那么子類依舊也會被認為是抽象類。
為什么會有抽象類梨睁?
A:因為純虛函數(shù)不能被調(diào)用鲸睛,所以包含純虛函數(shù)的類是無法實例化的,那么這時候就出現(xiàn)了一個抽象類坡贺,它作為多個子類的共同基類官辈,就相當于給多個子類提供一個公共的接口,我們可以通過定義這個公共接口的指針或引用遍坟,指向派生類的某個對象拳亿,這樣就可以通過它來訪問派生類對象中的虛函數(shù)
什么是靜態(tài)聯(lián)編、動態(tài)聯(lián)編
- 靜態(tài)聯(lián)編:是程序的匹配愿伴、連接在編譯階段實現(xiàn)肺魁,重載函數(shù)就是靜態(tài)聯(lián)編
- 動態(tài)聯(lián)編:當程序運行到這一塊才進行聯(lián)編,如swich和if
虛函數(shù)表是如何實現(xiàn)的隔节?
先思考一個問題鹅经,編譯器是在什么時候?qū)崿F(xiàn)不同對象能調(diào)用同名函數(shù)綁定關(guān)系的?
在創(chuàng)建對象的時候怎诫,編譯器偷偷給對象加了一個vptr指針瘾晃。只要我們類中定義了虛函數(shù),那么在實例化對象的時候刽虹,就會給對象添加一個vptr指針酗捌,類中創(chuàng)建的所有虛函數(shù)的地址都會放在一個虛函數(shù)表中,vptr指針就指向這個表的首地址涌哲。
虛函數(shù)的效率與普通函數(shù)比較
虛函數(shù)效率低胖缤,因為通過vptr指針調(diào)用重寫的函數(shù)是在程序運行時進行的,需要通過尋址操作找到該函數(shù)才能真正調(diào)用阀圾。而普通成員函數(shù)在編譯時就確定了調(diào)用的函數(shù)哪廓。
在構(gòu)造函數(shù)中定義虛函數(shù)會出現(xiàn)什么情況?
看以下代碼初烘,思考一下此時虛函數(shù)的調(diào)用
class Parent{
public:
Parent(int a=0){
this->a = a;
print();}
virtual void print(){cout<<"Parent"<<endl;}
private:
int a;
};
class Son:public Parent{
Son(int a=0,int b=0):Parent(a){
this->b = b;
print();}
virtual void print(){cout<<"Son"<<endl;}
};
void main(int argc, char const *argv[]){
Son s;
return 0;
}
兩個類中構(gòu)造函數(shù)中涡真,都只會調(diào)用自己類中的print()函數(shù)分俯。
為什么呢?因為Son對象在實例化時哆料,先調(diào)用基類構(gòu)造函數(shù)缸剪,存在虛函數(shù),將vptr指向基類的虛函數(shù)表东亦,調(diào)用派生類構(gòu)造函數(shù)杏节,存在虛函數(shù),將vptr指向派生類的虛函數(shù)表典阵。所以都只會調(diào)用自己類中的虛函數(shù)奋渔。
如果子類重寫了父類的某一虛函數(shù),那么父類的該虛函數(shù)就被隱藏壮啊,無論以后怎么調(diào)用嫉鲸,調(diào)用同名虛函數(shù)調(diào)用的都是子類虛函數(shù)
為什么析構(gòu)函數(shù)經(jīng)常定義為虛析構(gòu)函數(shù)
虛析構(gòu)函數(shù):只有當一個類被定義為基類的時候,才會把析構(gòu)函數(shù)寫成虛析構(gòu)函數(shù)歹啼。
為什么一個類為基類玄渗,析構(gòu)函數(shù)就需要寫成虛析構(gòu)?
假設(shè)現(xiàn)在有一個基類指針染突,指向派生類捻爷。此時釋放基類指針,如果基類沒有虛析構(gòu)函數(shù)份企,此時只會看指針的數(shù)據(jù)類型也榄,而不會看指針指向的數(shù)據(jù)類型,所以此時會發(fā)生內(nèi)存泄露司志。