姓名:張立斐 ? 學(xué)號:19020700001? ?學(xué)院:電子工程學(xué)院?
轉(zhuǎn)自:https://blog.csdn.net/lvliang2017232003/article/details/88804365
【嵌牛導(dǎo)讀】C++學(xué)習(xí)
【嵌牛鼻子】C++
【嵌牛提問】如何學(xué)習(xí)C++?
【嵌牛正文】
1.派生類不能直接訪問基類的私有成員捐凭,必須通過基類方法進(jìn)行键耕。 派生類可以直接訪問(調(diào)用)基類的公有類方法。
? 創(chuàng)造派生類對象時柑营,程序先創(chuàng)建基類對象.? 派生類構(gòu)造函數(shù)必須使用基類構(gòu)造函數(shù)屈雄。
class TablePlayer{ //基類聲明,在.h文件中
private:
? string? firstname;
? string lastname;
public:
? TablePlayer(const string & fn="none", const string & ln="none");
? void Name() const;
};
//方法的實(shí)現(xiàn)在.cpp文件中
TablePlayer::TablePlayer(const string & fn, const string & ln) : firstname(fn),
? ? ? ? ? ? ? ? ? ? ? ? lastname(ln) {}? //成員初始化列表法
void TablePlayer::Name() const
{ std::cout<<lastname<<","<<firstname }?
class ReatedPlayer: public TablePlayer{ //公有派生類
private:
? unsigned int rating;
public:
? ReatedPlayer(unsigned int r, const string & fn="none",
? ? ? ? ? ? ? const string & ln="none")
? ReatedPlayer(unsigned int r,const TablePlayer & tp); //
? unsigned int Rating() const {return rating; }
};
//派生類的構(gòu)造函數(shù)
ReatedPlayer::ReatedPlayer(unsigned int r, const string & fn,
? ? ? ? const string & ln) : TablePlayer(fn,ln) //將fn,ln參數(shù)從派生類構(gòu)造函數(shù)傳遞到基類構(gòu)造函數(shù)
{
? rating=r;
}
ReatedPlayer::ReatedPlayer(unsigned int r, const string & fn,
? ? ? ? const string & ln) //未調(diào)用基類構(gòu)造函數(shù)時官套,等效于使用默認(rèn)構(gòu)造函數(shù)? : TablePlayer()
{
? rating=r;
}
ReatedPlayer::ReatedPlayer(unsigned int r,const TablePlayer & tp):TablePlayer(tp)
{
? rating=r;
}
ReatedPlayer::ReatedPlayer(unsigned int r,const TablePlayer & tp):
? ? TablePlayer(tp),rating(r) {}
int main (void){
using std::cout; using std::endl;
TablePlayer player1("Bob", "Boomede");
RatedPlayer rplayer1(1140, "Mallay","Duck"); //創(chuàng)建派生類對象
rplayer1.Name(); //派生類可以直接調(diào)用基類的公有類方法
}
2.派生類的對象和地址可以賦給基類引用和指針酒奶。 但不能將基類的對象和地址賦給派生類引用和指針
TablePlayer? & rt=rplayer;? TablePlayer? * pt= & rplayer; (合法)
3. C++的3種繼承方式:公有繼承 ,保護(hù)繼承 和 私有繼承 奶赔。公有繼承(is-a 關(guān)系 即派生類對象也是一個基類對象)
? 繼承可以在基類基礎(chǔ)上添加屬性惋嚎,但不能刪除基類屬性。
4. 同一個方法在派生類和基類中的行為不同站刑,即 同一方法的行為隨上下文而異另伍,這種行為叫多態(tài)。
? 實(shí)現(xiàn)多態(tài)公有繼承的兩種方法:1) 在派生類中重新定義基類? 2)使用虛方法(聲明函數(shù)時在前面加關(guān)鍵字virtual)具體實(shí)現(xiàn)不用加绞旅。
在基類中將派生類會重新定義的方法聲明為虛方法. (程序?qū)⒏鶕?jù)對象類型而不是引用或指針類型來選擇方法版本)
方法在基類中被聲明為虛函數(shù)后摆尝,派生類中將自動成為虛函數(shù)(也可加virtual指明哪些是虛函數(shù))。
為基類聲明一個虛析構(gòu)函數(shù)也是一種慣例因悲《楣【確保釋放派生類對象時,按正確的順序調(diào)用析構(gòu)函數(shù)晃琳。 先調(diào)用派生類析構(gòu)函數(shù)讯检,再調(diào)用基類構(gòu)造函數(shù)】 分析:delete pt ; 釋放內(nèi)存時,先應(yīng)用派生類默認(rèn)的析構(gòu)函數(shù)卫旱,釋放派生類對象內(nèi)存人灼,再調(diào)用基類中的虛析構(gòu)函數(shù)來釋放內(nèi)存。 如果不在基類中聲明虛析構(gòu)函數(shù)顾翼,直接調(diào)用基類的析構(gòu)函數(shù)投放,將只釋放部分內(nèi)存,不會釋放派生類中新的類成員指向的內(nèi)存暴构。
/*基類Brass公有成員函數(shù)ViewAcct聲明前無virtual*/
Brass dom(" Dominic Banker",1121,4182.45);//基類對象
BrassPlus dot("Doroty Banker",1238,2592.00);//派生類對象
Brass & b1=dom;
Brass & b2=dot; //派生類可以直接賦給基類
b1.ViewAcct(); // 用Brass::ViewAcct()
b2.ViewAcct(); // 用Brass::ViewAcct()
/*基類Brass公有成員函數(shù)ViewAcct聲明前有virtual*/
b1.ViewAcct(); // 用Brass::ViewAcct()
b2.ViewAcct(); // 用BrassPlus::ViewAcct() 根據(jù)對象類型而非引用選擇版本
5. 在派生類的成員函數(shù)實(shí)現(xiàn)中:調(diào)用基類公有函數(shù)時跪呈,可直接調(diào)用如 doubal bal=Balance()段磨,若派生類中虛函數(shù)ViewAcct()中要調(diào)用基類的虛函數(shù)ViewAcct(),要用作用域解析符,應(yīng)寫為 Brass::ViewAcc()
6. 可以使用一個數(shù)組來表示多種類型的對象耗绿,這就是多態(tài)性苹支。
? Brass * p_client[N]; //Brass[i]指針可以指向Brass對象也可指向BrassPlaus對象
p_client[i]=new Brass(temp,tempnum,tempbal);
p_client[j]=new BrassPlaus(temp,tempnum,tempbal,tmax,trate); //滿足不同的條件用相應(yīng)的賦值語句
多態(tài)性由以下代碼提供:
for (int i=0;i<N;i++){? p_client[i]->ViewAcct();? }
7.在編譯過程中進(jìn)行聯(lián)編, 稱為靜態(tài)聯(lián)編 误阻; (可以直接確定編譯哪個函數(shù))
? 編譯器必須生成能夠在程序運(yùn)行時選擇正確的虛函數(shù)代碼债蜜,稱為動態(tài)聯(lián)編。
8. 動態(tài)聯(lián)編可以重新定義類方法究反, 靜態(tài)聯(lián)編效率高寻定。
9.編譯器處理虛函數(shù)的方法:
? 給每個對象添加一個隱藏成員。這個成員保存了一個指向函數(shù)地址數(shù)組的指針精耐,這種數(shù)組稱為虛函數(shù)表(vtbl:virtual function table,)狼速。虛函數(shù)表中存儲了為類對象聲明的虛函數(shù)的地址。 虛函數(shù)地址表時一個數(shù)組卦停。
【基類對象中隱含一個指針向胡,該指針指向基類中所有虛函數(shù)的地址表。派生類對象將隱含一個指向獨(dú)立地址表的指針惊完。? ? ? ? ? 如果派生類提供了虛函數(shù)的新定義僵芹,該虛函數(shù)表將保存為新的地址,如果派生類沒有重新定義虛函數(shù)小槐,該vtbl將保存基類函數(shù)的原始地址】
(無論類中的虛函數(shù)是1個還是10個拇派,只在對象中添加1個地址成員,只是表的大小不同)
10. 友元不能是虛函數(shù) (友元不是類成員凿跳,只有成員才能是虛函數(shù))
11.重新定義的繼承方法并不是重載件豌。
? 重新定義的繼承方法,應(yīng)確保與基類的原型完全相同拄显。但如果有返回類型苟径,返回是基類引用或指針,則在派生類繼承方法修改為返回指向派生類的引用或指針躬审。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class Dwelling {? public: virtual Dwelling & build (int n)? } ;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class Hovel:public Dwelling {? public: virtual Hovel & build (int n) };
如果基類聲明被重載巫员,則應(yīng)在派生類中重新定義所有的重載版本月匣。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class Dwelling {? public: virtual void? showperks ( ) const ;? virtual void? showperks (int a ) const ;? } ;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? class Hovel:public Dwelling {? public: virtual void? showperks ( ) const ;? virtual void? showperks (int a ) const ;? };
12.? 派生類成員可以直接訪問基類的保護(hù)成員,但不能直接訪問基類的私有成員毡鉴。
? ? ? 對外部世界來說石挂,保護(hù)成員和私有成員類似博助;對派生類來說,保護(hù)成員和公有成員類似痹愚;
? ? ? 對類數(shù)據(jù)成員最好采用私有訪問控制富岳,不要使用保護(hù)訪問控制蛔糯;同時通過基類的方法使派生類訪問基類數(shù)據(jù);
? ? ? ? 對于成員函數(shù)窖式,保護(hù)控制有用蚁飒,讓派生類訪問公眾不能使用的內(nèi)部函數(shù)
13. 復(fù)雜抽象基類(ABC:abstract base class) :只定義接口,不定義實(shí)現(xiàn)萝喘。至少使用一個純虛函數(shù)接口淮逻,從ABC派生的類將根據(jù)派生類的具體特征,使用常規(guī)虛函數(shù)來實(shí)現(xiàn)這種接口阁簸。 要成為真正的ABC爬早,必須至少包含一個純虛函數(shù)。 原型中的=0使虛函數(shù)成為純虛函數(shù)启妹。
【當(dāng)N類和M類有一定的共性筛严,但M類不需要完全繼承N類的數(shù)據(jù)和方法時,可以將M和N的共性放到ABC中饶米,然后從ABC中派生出N類和M類桨啃。 ABC類指針可以同時管理M類和N類對象】 原型使用=0指出類是一個抽象基類。 C++中允許純虛函數(shù)有定義咙崎。
例如: 橢圓和圓兩個類优幸, 共同點(diǎn)是中心坐標(biāo)方法,和移動Move()方法是相同的褪猛,但面積Area()是不同的网杆。
? ? ? ? ? 在ABC中不能實(shí)現(xiàn)Area()方法。 C++通過用純虛函數(shù)提高未實(shí)現(xiàn)的函數(shù)伊滋,純虛函數(shù)聲明的結(jié)尾處為=0碳却;
? ? ? ? ? ? 當(dāng)類聲明中包含純虛函數(shù)時,不應(yīng)該創(chuàng)建該類的對象笑旺。
//橢圓和圓的ABC類?
class BaseEllipse{? //聲明中含有純虛函數(shù)昼浦,不能創(chuàng)建BaseEllipse類對象
? private:
? ? double x; //橢圓和圓的共性
? ? double y;
? public:
? ? BaesEllipse(double x0=0,double y0=0) :x(x0),y(y0){}
? ? virtual ~BaesEllipse();
? ? void Move(int nx,ny) { x=nx; y=ny; } //橢圓和圓的共性
? ? virtual double Area() const=0; //純虛函數(shù)? 橢圓和圓的不同? ?
};
14. 構(gòu)造函數(shù)、析構(gòu)函數(shù)筒主、賦值函數(shù)关噪、友元函數(shù)不能被繼承。
————————————————
版權(quán)聲明:本文為CSDN博主「lvliang2229」的原創(chuàng)文章乌妙,遵循CC 4.0 BY-SA版權(quán)協(xié)議使兔,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lvliang2017232003/article/details/88804365