Effective C++筆記 —— 第六章

  1. public繼承是is-a的關係
  2. derived class作用域被嵌套在base class作用域內
  3. 不重新定義繼承而來的缺省參數值,virtual函數動態綁定,而缺省參數值卻是靜態綁定
    在這裏插入圖片描述
  4. 避免遮掩繼承而來的名稱,即使base classes和derived classes內的函數有不同的參數類型也適用,而且不論函數是virtual 或 non-virtual 一樣適用
    class Base{
    private:
    int x;
    public:
    virtual void mf1()=0;
    virtual void mf1(int);
    virtual void mf2();
    void mf3();
    void mf3(double);
    ...
    };
    class Derived:public Base{
    public:
    virtual void mf1();
    void mf3();
    void mf4();
    };
    
    Derived d;
    int x;
    ...
    d.mf1(); //沒問題,調用Derived::mf1
    d.mf1(x);   //錯誤,因爲Derived::mf1遮掩了Base::mf1
    d.mf2();   //沒問題,調用Base::mf2
    d.mf3();   //沒問題,調用Derived::mf3
    d.mf3(x);   //錯誤,因爲Derived::mf3遮掩了Base::mf3
    
    如果你繼承base class並加上重載函數,而又希望重新定義或覆寫其中一部分,那麼你必須爲那些原本會被遮掩的每個名稱引入一個using聲明式,否則某些你希望繼承的名稱會被遮掩
    class Base{
    private:
    int x;
    public:
    virtual void mf1()=0;
    virtual void mf1(int);
    virtual void mf2();
    void mf3();
    void mf3(double);
    ...
    };
    class Derived:public Base{
    public:
    using Base::mf1; //讓Base class內名爲mf1和mf3的所有東西在Derived作用域內都可見
    using Base::mf3;
    virtual void mf1();
    void mf3();
    void mf4();
    };
    
    Derived d;
    int x;
    ...
    d.mf1(); //沒問題,調用Derived::mf1
    d.mf1(x);   //現在沒問題了,調用Base::mf1
    d.mf2();   //沒問題,調用Base::mf2
    d.mf3();   //沒問題,調用Derived::mf3
    d.mf3(x);   //現在沒問題了,調用Base::mf3
    
    如果Derived唯一想繼承mf1那個無參數版本,可以用private繼承,用一個簡單的轉交函數
    class Derived:private Base{
    public:
    virtual void mf1()
    {Base::mf1();}
    };
    
  5. 絕不重新定義繼承而來的non-virtual函數。non-virtual函數是靜態綁定的,由於pB被聲明爲一個pointer-to-B,通過pB調用的non-virtual函數永遠是B所定義的版本,即使pB指向一個類型爲“B派生之class”的對象
    	D x;
    	B* pB=&x;
    	pB->mf();     //調用B::mf
    	pD->mf();     //調用D::mf
    	class B{
    	public;
    		void mf();
    	};
    	class D ::public B
    	{
    	public;
    		void mf();
    	};
    	```
    	當mf被調用,任何一個D對象都可能表現出BD的行爲:決定因素不再對象自身,而在於“指向該對象之指針”當初的聲明類型
    	或者理解爲public繼承是is-a的關係,適用於B的每一件事也適用於D,如果重新定義non-virtual設計便出現矛盾
    
  6. private base class繼承而來的所有成員,在derived class中都會變成private屬性,縱使它們在base class中原本是protected或是public屬性。private繼承意味着根據某物實現出,如果class D private 繼承class B,用意是爲了採用class B內已經具備的某些特性,不是因爲B對象和D對象存在任何觀念上的關係
  7. 當base class是一個空類時(只含typedef或者static成員變量或者non-virtual函數時),選擇private繼承而不是複合,因爲複合是base class會有一個字節大小然後會根據內存對齊進行調整,private繼承不會增加derived class大小;或者當需要訪問base class成員或者重寫virtual函數時,採用private繼承,否則儘量用複合
  8. 非必要儘量不使用virtual bases;如果必須使用virtual base class,儘可能避免在其中放置數據
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章