Effective C++学习第十天
條款36:絕不重新定義繼承而來(lái)的non-virtual函數(shù)
? ? ? ? ? non-virtual函數(shù)執(zhí)行的是靜態(tài)綁定,在編譯器就已經(jīng)決定,因此對(duì)象對(duì)用的函數(shù)只和指針的類型有關(guān),而與指針?biāo)傅膶?duì)象無(wú)關(guān);記住non-virtual函數(shù)的性質(zhì):不變性凌駕于特異性;
條款37:絕不重新定義繼承而來(lái)的缺省參數(shù)值
? ? ? ? ?靜態(tài)類型是指在程序中聲明時(shí)使用的類型,動(dòng)態(tài)類型是指目前所指對(duì)象的類型,動(dòng)態(tài)類型變現(xiàn)為一個(gè)對(duì)象將會(huì)有什么樣的行為;
? ? ? non-virtual和參數(shù)缺省值執(zhí)行的是靜態(tài)綁定,virtual執(zhí)行的是動(dòng)態(tài)綁定,代碼分析:
class shape{
public:
? ?enum shapecolor { red, green, blue };
? virtual void draw(shapecolor color=red) const=0;
};
class rectangle:public shape{
public:
? ? ? ? ? virtual void draw(shapecolor color=green) const;//糟糕的操作
? ? ? ? ?...
};
class circle:public shape{
public:
? ? ? ? ? ? ? virtual void draw(shapecolor color)const;
? ? ? ? ? ? ? ...
};
調(diào)用 shape *pr=new rectangle;
? ? ? ? pr->draw( );//執(zhí)行的代碼為rectangle::draw(shape::red):
? ? ? ? ? ? ? ? ? ? ? ? ? //相當(dāng)于shape執(zhí)行缺省,rectangle執(zhí)行virtual函數(shù),一人一半,神奇的操作;
C++這樣設(shè)計(jì)的原因:運(yùn)行期效率,如果缺省值是動(dòng)態(tài)綁定,編譯器就必須用某種方法在運(yùn)行期為virtual函數(shù)決定適當(dāng)?shù)膮?shù)缺省值,這比目前實(shí)現(xiàn)的在編譯期決定的機(jī)制更慢更加復(fù)雜;
條款38:通過(guò)復(fù)合塑模出has-a或者根據(jù)某物實(shí)現(xiàn)出
? ? ? ? ? 復(fù)合是類型之間的一種關(guān)系,當(dāng)某種類型的對(duì)象內(nèi)含它種類型的對(duì)象,就是這種關(guān)系;復(fù)合有兩種意義,復(fù)合意味著has-a(有一個(gè))或is-implemented-in-terms-of(根據(jù)某物實(shí)現(xiàn)出);
? ? ? ? ?如何區(qū)分is-a(是一種)和is-implemented-in-terms-of(根據(jù)某物實(shí)現(xiàn)出)這兩種關(guān)系,可以通過(guò)public繼承中D繼承B,D對(duì)象也是B對(duì)象,反之B對(duì)象不是D對(duì)象來(lái)判斷;
條款39:明智而審慎地使用private繼承
? ? ? ? ? private繼承意味著implemented-in-terms-of(復(fù)合),它只有實(shí)現(xiàn)部分被繼承,接口部分省略;private繼承純粹是一種實(shí)現(xiàn)技術(shù),它在軟件設(shè)計(jì)層面上沒(méi)有意義,其意義只及于軟件實(shí)現(xiàn)層面;代碼分析:
? ? ? class person {...};
? ? ? class student:private person{ . . .};
? ? ? void eat(const person&p);
? ? ? person p;??? student s;? ??? eat(p);
? ? ? eat(s);//編譯不通過(guò)
原因:1)private繼承中編譯器不會(huì)自動(dòng)將一個(gè)derived class對(duì)象轉(zhuǎn)換為一個(gè)base class對(duì)象;2)private繼承而來(lái)的所有成員在derived? class中都會(huì)變成private屬性,縱使它們?cè)赽ase class中原本是public或者protected;? ?
? ? ? ?盡可能的多用復(fù)合,必要的時(shí)候才使用private繼承(protected成員和virtual函數(shù)牽涉進(jìn)來(lái)的時(shí)候,或者繼承一個(gè)empty class時(shí)候可以采用private繼承)
? ? ? ?需求:定義一個(gè)類B(繼承一個(gè)類B_B),使得這個(gè)類的派生D不能調(diào)用B_B的成員函數(shù);
設(shè)計(jì)1:private繼承
class B_B{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?class D:private B_B{
public:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?private:?
? ? ? ?explicit B_B(int tickfrency);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? virtual void ontick( ) const;
? ? ? ?virtual void ontick( )const;
};? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? };
設(shè)計(jì)2:繼承+復(fù)合
class D{
private:
? ? ? ? class widgettimer:public B_B{
? ? ? ? ?public:? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ?virtual void ontick( )const;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ...
? ? ? ? };
? ? widgwttimer timer;
}
在D內(nèi)聲明一個(gè)嵌套式private class,后者以public繼承B_B并重新定義ontick,然后放這個(gè)類型在D對(duì)象內(nèi);
選擇方案2不選擇方案1的原因:1)想阻止D的derived class重新定義ontick函數(shù);2)降低D編譯的依存性;
? ? ? ? ? empty class:沒(méi)有non_static成員變量,沒(méi)有virtual函數(shù),沒(méi)有virtual base class;empty class數(shù)據(jù)大小并不是零,C++規(guī)定凡是獨(dú)立對(duì)象都必須有非零大小(這個(gè)約束不針對(duì)derived class 中的base class成分,它們是非獨(dú)立的),因此一個(gè)empty class 大小為1(C++規(guī)定安插一個(gè)char類型到空對(duì)象中);
? ? ? ? ?在繼承empty class中,如果選擇private繼承(EBO,empty base optimization,繼承空類),可能造成empty base的最優(yōu)化;
總結(jié)
以上是生活随笔為你收集整理的Effective C++学习第十天的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 周末父母剧情介绍
- 下一篇: Effective C++学习第十一天