多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > 《Effective C++》:條款36-條款37

《Effective C++》:條款36-條款37

來源:程序員人生   發布時間:2015-09-17 08:13:49 閱讀次數:2666次

  • 條款36絕不重新定義繼承而來的non-virtual函數
  • 條款37絕不要重新定義繼承而來的缺省參數值

條款36:絕不重新定義繼承而來的non-virtual函數

以1個例子來展開本條款論述內容。假定class D是class B的派生類,class B中有1個public成員函數mf:

class B{
public:
    void mf();
    ……
};

class D: public B {……};

由1下方式調用

D x;
B* pB=&x;
pB->mf();
D* pD=&x;
pD->mf();

上面的兩次調用函數mf得到的行動相同嗎?雖然mf是個non-virtual函數,但是如果class D中有自己定義的mf版本,那就行動真的不同。

class D: public B {
public:
    void mf();//遮掩了B::mf。見條款33
……};
pB->mf();//調用B::mf
pD->mf();//調用D::mf)。

之所以行動不1致,是由于non-virtual函數是靜態綁定的(statically bound,條款 37)。pB被聲明為1個pointer-to-B,通過pB調用的non-virtual函數永久是B所定義的版本。但是virtual函數是動態綁定(dynamically bound,條款 37),所以virtual函數不受這個束縛,即通過指針調用,實際調用的函數是指針真正指向對象的那個函數。

如果你打算在class D中重新定義繼承自class B的non-virtual函數,D對象極可能會出現行動不1致行動。更明確1點,即任何1個D對象都可能表現出B或D的行動;決定因素不在對象本身,而在于“指向該對象之指針”當初聲明類型。References也會展現出和指針1樣難以理解的行動。

前面已說過,public繼承是is-a 關系(條款 32)。**條款**34說過,class內聲明1個non-virtual函數會為該class建立1個不變性(invariant),它凌駕其特異性(specialization)。將這兩個觀點實施到class B和class D上和non-virtual函數B::mf上,那末

  • 適用于B對象的每件事,也適用于D對象。(is-a 關系)
  • B的derived classes1定會繼承mf的接口和實現,由于mf是1個non-virtual函數。

現在在D中重新定義mf,就會有矛盾。1、如果D真的有必要重新實現mf(不同于B的),那末is-a 關系就不成立,由于每一個D都是B不再為真;既然這樣,就不應當以public情勢繼承。2、如果D必須以public方式繼承B,且D有需求實現不同的mf,那末久不能反應出不變性凌駕特異性;既然這樣就應當聲明為virtual函數。3、如果每一個D是1個B為真,且mf真的可以反應出不變性凌駕特異性的性質,那末D久不需要重新定義mf了。

不論上面那個觀點,結論都相同:任何情況下都不應當重新定義1個基礎而來的non-virtual函數。

條款 7已知道,base class內的析構函數應當是virtual;如果你違背了條款 7,你也就違背了本條款,由于析構函數每一個class都有,即便你沒有自己編寫。

總結

  • 絕對不要重新定義繼承而來的non-virtual函數。

條款37:絕不要重新定義繼承而來的缺省參數值

在繼承中,只能繼承兩種函數:virtual和non-virtual。在條款 36中我們學到,不能重新定義1個繼承而來的non-virtual函數。本條款討論的是繼承virtual函數問題,再具體1點:繼承1個帶有缺省參數值的virtual函數。

我們應當知道,virtual函數是動態綁定(dynamically bound),缺省參數值卻是靜態綁定(statically bound)。

對象的靜態類型(static type)是它在程序中被聲明時采取的類型,例如

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;
    /*客戶調用上面函數時,如果使用對象調用,必須指定參數值,由于靜態綁定下這個函數不從base繼承缺省值。*/
    /*如果使用指針或援用調用,可以不指定缺省參數值,動態綁定會從base繼承缺省參數值*/
    ……
};

這個繼承很簡單。現在這樣使用

Shape* ps;
Shape* pc=new Circle;
Shape* pr=new Rectangle;

這些指針類型都是pointer-to-Shape類型,都是靜態類型Shape*。對象的動態類型是指“目前所指對象類型”。動態類型可以表現出1個對象將會有甚么行動。pc動態類型是Circle*,pr動態類型是Rectangle*,ps沒有動態類型(它沒有指向任何對象)。動態類型可以在履行進程中改變,重新賦值可以改變動態類型。

virtual函數是動態綁定的,調用哪1份函數實現的代碼,取決于調用的那個對象的動態類型。

pc->draw(Shape::Red);
pr->draw(Shape::Red);

這樣調用無可非議,都帶有參數值。但是如果不帶參數值呢

pr->draw();//調用Rectangle::draw(Shape::Red)

上面調用中,pr動態類型是Rectangle*,所以調用Rectangle的virtual函數。Rectangle::draw函數缺省值是GREEN,但是pr是靜態類型Shape*,所以這個調用的缺省參數值來自Shape class,不是Rectangle class。這次調用兩個函數各出了1半的力。

C++之所以使用這么奇異的運作方式,是由于效力問題。如果缺省參數值動態綁定,編譯器必須有某種辦法在運行期為virtual函數決定適當的參數缺省值。這比目前實行的“在編譯器決定”的機制更慢且更復雜。為了履行速度和編譯器實現上的簡易度,C++做了這樣的取舍。

我們嘗試遵照這個規則,給base class和derived class提供相同參數值

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=Red) const;
    ……
};

這樣問題又來了,代碼重復且帶著相依性(with dependencies):如果Shape內缺省參數值改變了,那末derived classes的缺省參數值也要改變,否則就會致使重復定義1個繼承而來的缺省參數值。

當時如果的確需要derived classes的缺省參數值,那末就需要替換方法。條款 35列出了1些virtual函數的替換方法,例如NVI手法:

class Shape{
public:
    enum ShapeColor{ Red, Green, Blue};
    void draw(ShapeColor=Red) const
    {
        doDraw(color);
    }
    ……
private:
    virtual void doDraw(ShapeColor color) const=0;//真正在這里完成工作
};
class Rectangle: public Shape{
public:
    ……
private:
    virtual void draw(ShapeColor color) const;
    ……
};

由于non-virtual函數不會被derived覆寫(條款 36),這個設計很清楚的使得draw函數的color缺省參數值總是Red。

總結

  • 不要重新定義1個繼承而來的缺省參數值,由于缺省參數值是靜態綁定,而virtual函數(你唯1應當覆寫的東西)是動態綁定。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产叼嘿视频 | 久久精品国产线看观看亚洲 | 免费观看影视传媒公司 | 国产欧美另类 | yellow网站在线观看 | 五月伊人婷婷 | 国产亚洲3p一区二区三区 | 国产高清看片日韩欧美久久 | 亚洲国产成人久久99精品 | 激情网站视频 | 欧美大陆日韩 | 亚洲区精品久久一区二区三区 | 久久久久国产精品嫩草影院 | 视频一区二区国产无限在线观看 | 成人看片毛片免费播放器 | 久久无码av三级 | 伊人99在线观看 | wwwww在线观看 | 欧美最猛黑人xxxx黑人 | 亚洲国产成人资源在线桃色 | 国产第一页精品 | 国产男人女人做性全过程视频 | 日韩精品区 | 亚洲欧美日韩中文字幕网址 | 18在线观看网站 | 亚洲成人高清在线观看 | 印度最猛性xxxxx | 91精品福利在线观看 | 国产人成午夜免费看 | 男人久久 | 亚洲小说春色综合另类小说 | 日韩欧美印度一级毛片 | 亚洲一区二区在线 | 国产成人精品视频一区二区不卡 | 中文字幕最新在线 | 亚洲免费毛片 | 亚洲精品99久久久久久欧美版 | 中文无码日韩欧免费视频 | 国产精品久久久免费视频 | 国产精品18久久久久网站 | 亚洲影视先锋 |