Effective C++学习第九天
條款32:確定你的public繼承塑模出is-a模型
? ? ? ?class D(derived)以public形式繼承class B(base),則每一個(gè)類型為D的對(duì)象同時(shí)也是一個(gè)類型為B的對(duì)象,反之不成立,因此B比D表現(xiàn)出更加一般化的概念,而D比B表現(xiàn)出更特殊化的概念。在C++領(lǐng)域里面,任何函數(shù)如果希望獲得一個(gè)類型為B的實(shí)參,都也愿意接受一個(gè)類型為D的對(duì)象,這就是is-a(是一種)的關(guān)系;代碼分享:
class ractangle{
public:
virtual void setheight(int newheight);
virtual void setwidth(int newwidth);
virtual int height( ) const;
virtual int width( ) const;
};
void makebigger(rectangle &r){
int oldheight=r.height( );
r.setwidth(r.width( )+10);
assert(r.height()==oldheight);//assert為真
}
class square:public rectangle{ ...};
square s;
assert(s.width()==s.height( ));//assert為真
makebiggle(s);
assert(s.width()==s.height( ));//asseert為真 ,為什么s沒有發(fā)生變化;
在本例分析中,某些可施行在矩形身上的事情(寬度可獨(dú)立于高度被修改)卻沒辦法施行在正方形身上(寬度和高度一樣),但public主張,能夠施行在base class對(duì)象上的每一件事情,都能施行于derived class對(duì)象上,所以正方形和矩形的例子中不滿足is-a模型;pulic就意味著is-a模型,因此在繼承中確定你的class之間的關(guān)系,并合理塑造它們;
條款33:避免遮掩繼承而來的名稱(繼承而導(dǎo)致的作用域問題)
? ? ? ? ? 在public繼承中,derived class中的成員函數(shù)會(huì)將base class中重名的成員函數(shù)覆蓋掉,從而出現(xiàn)因繼承導(dǎo)致成員函數(shù)調(diào)用問題;因此使用public繼承但又不繼承那些重載函數(shù),這就違背了public繼承中的is-a原則;
? ? ? ? ?如果你想繼承base class并加上重載函數(shù),而你希望重新定義或者復(fù)寫其中一部分,那么你必須為那些原本會(huì)被遮掩的每個(gè)名稱引用一個(gè)using的聲明,否則某些你希望繼承的名稱會(huì)被遮掩;
? ? ? ? ?如果derived以private方式繼承的base,如果使用using聲明,那么給定名稱的函數(shù)會(huì)在derived中都可見,這并不是我們希望達(dá)到的目的,這時(shí)候我們可以使用一個(gè)簡單的轉(zhuǎn)交函數(shù);
class base{
public:
virtual void mf1()=0;
virtual void mf1(int);
...
};
class derived:private base {
public:
? virtual void mf1( ){//轉(zhuǎn)交函數(shù)
? ? ? ? base::mf1( );//inline函數(shù)
?}
};
條款34:區(qū)分接口繼承和實(shí)現(xiàn)繼承
? ? ? ? ? public繼承分為函數(shù)接口繼承和函數(shù)實(shí)現(xiàn)繼承;
? ? ? ? ? 1)對(duì)于pure virtual函數(shù),它有兩個(gè)特性,它們必須被任何“繼承了它們”的具象class重新聲明,而且它們?cè)诔橄骳lass中通常沒有定義,因此聲明一個(gè)pure virtual函數(shù)的目的是為了derived class只繼承接口(只具體接口繼承);
? ? ? ? ?引申:我們可以給pure virtual函數(shù)提供定義,也就是說你可以給base中的pure virtual函數(shù)提供一份實(shí)現(xiàn)代碼,C++并不會(huì)發(fā)出警告和錯(cuò)誤,但調(diào)用它的唯一途徑就是:調(diào)用時(shí)明確指出其class路徑;(一直以為pure virtual函數(shù)不能在base內(nèi)實(shí)現(xiàn))
? ? ? ? ?2)derived class繼承函數(shù)接口,但是impure virtual函數(shù)會(huì)提供一份實(shí)現(xiàn)代碼,derived class可能會(huì)賦寫它;聲明簡樸的impure virtual 函數(shù)的目的,是讓derived classes繼承該函數(shù)的接口和缺省實(shí)現(xiàn)(具體指定接口繼承和缺省實(shí)現(xiàn)繼承);
? ? ? ? ?如果在繼承過程中,derived class中沒有重新定義virtual class,那么就默認(rèn)使用base class中的virtual函數(shù);如果兩個(gè)class都共享著一份相同的性質(zhì),可以把這份相同的性質(zhì)搬到base class中,從而避免代碼重復(fù),這是典型的面向?qū)ο蟮脑O(shè)計(jì)方法;
? ? ? ?3)對(duì)于一個(gè)non-virtual函數(shù),意味著它并不打算在derived class中有不同的行為,實(shí)際上一個(gè)non-virtual成員函數(shù)所表現(xiàn)出來的不變性凌駕其特異性,因此不管derived class變得多特異化,它的行為都不可以被改變;聲明一個(gè)non-virtual函數(shù)的目的是為了令derived class繼承函數(shù)的接口及一份強(qiáng)制性的實(shí)現(xiàn)(具體指定接口及強(qiáng)制性實(shí)現(xiàn)繼承);
總結(jié)
以上是生活随笔為你收集整理的Effective C++学习第九天的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地下城与勇士阿修罗时装选择
- 下一篇: css box-shadow 单边 单角