Effective C++ 33 避免遮掩繼承而來的名稱,effective33

來源:互聯網
上載者:User

Effective C++ 33 避免遮掩繼承而來的名稱,effective33

 

  首先介紹一個原則LSP(Liskov Substitution Principle),如果Class D以Public方式繼承Class B,則所有B對象可以派上用場的任何地方,D對象一樣可以派上用場。

對於重載和重寫,相信大家都已經有所瞭解。這裡討論一下在public繼承的時候,重載函數的問題。

 

先看下面的例子:

 1 class Base   2     {   3     public:   4         virtual void mf1() = 0;   5         virtual void mf1(int);   6         virtual void mf2();   7         void mf3();   8         void mf3(double);   9         ...  10     private:  11         int x_;  12     };  13     class Derived:public Base  14     {  15     public:  16         virtual void mf1();  17         void mf3();  18         void mf4();  19         ...  20     };  


在基類中,mf1() 和mf3()都被重載,子類public繼承父類,這裡的子類覆蓋了父類中所有名為mf1和mf3的函數。因而以下調用有些會失敗。


Derived d;  int x;  ...  d.mf1(); // Derived::mf1  d.mf1(x); //錯誤 Derived::mf1 hiden Base::mf1  d.mf2();  // Base::mf2  d.mf3();  // Derived::mf3  d.mf3(x); //錯誤Derived::mf3 hiden Base::mf3


由此可見,及時子類和父類內的函數有不同的參數時,子類的函數還是會覆蓋所有父類中同名的函數。

這樣做的原因:避免從疏遠的父類中繼承重載函數。但是實際上,public繼承應該遵循LSP原則,即父類和子類是Is-a 的關係,所以我們可以通過using,顯示地實現對父類同名重載函數的繼承。


1 class Base{...}; //同上  2 class Derived:public Base{  3 public:  4     //讓Base class內名為mf1與mf3的所有東西在  5      //Derived範圍內都可見(並且都是public)  6     using Base::mf1;  7     using Base::mf3;  8     ....//同上          9 };  
Derived d;  int x;  ...  d.mf1(); //no problem. call Derived::mf1  d.mf1(x); //no problem. Base::mf1  d.mf2();  //no problem. call Base::mf2  d.mf3();  //no problem. call Derived::mf3  d.mf3(x); //no problem. Base::mf3  


如果你不想繼承所有的重載函數,則你不應該使用public繼承,因為這樣會違反LSP原則,你可以使用private繼承,為了選擇性的繼承重載函數,可以使用inline 轉交函數(forwarding function),具體實現如下:

 

 1 class Base   2 {   3 public:   4     virtual void mf1() = 0;   5     virtual void mf1(int);   6     ... //same as above   7 };   8 class Derived:private Base   9 {  10 public:  11     virtual void mf1()//轉交函數(forwarding function)  12     {  13         Base::mf1();   14     }  15     ...  16 };  17 ...  18 Derived d;  19 int x;  20 d.mf1(); //good! call Derived::mf1  21 d.mf1(x); //Error as suppose,Base::mf1() was hidden.  

 

關鍵:

  子類內的名稱會遮掩父類內的名稱,在pubilc繼承下,不應該這樣做。

  為了使被遮掩的名稱可見,使用using聲明或者轉交函數。

 


effective c++ item33出問題啦不知道是不是要在c99的標準下才可以哦 大蝦幫忙看看

我來給你好好講講吧!你還是沒搞懂那個函數的範圍,前面public:
/****************/
using base::mf1;
/****************/
virtual void mf1()
{
cout<<"derived::mf1"<<endl;
}
這裡這句using base::mf1就是讓base類的mf1(有這個函數名稱的都是)函數在derived裡面可見,要不然重載的mf1在derived裡面是不可見的,也就是說derived裡面有一個base::void mf1(int temp=0)還有一個derived::void mf1()而你base裡面的mf1函數的參數又有預設值,你用derived 調用的時候肯定有引起歧義的。
第二次你修改之後,改成private 繼承時,結果還是一樣,主要是你base裡面的函數重載衝突了,原因就是你mf1裡面的參數有預設值。還有你在derived 裡的virtual void mf1()裡面base::mf1()是肯定不對的,因為純虛函數是不能直接被調用的。
如果還不能明白的話,就好好交流下吧!
希望能幫到你!
 
對於c++中虛函數重載的問題

大家都說錯了,沒說到重點。
這不是什麼虛函數限制,主要原因在於函數調用名稱解釋的問題。按照名稱解析規則,func在類derive中已經找到,所以後續的按參數匹配的名稱尋找會在該類中進行。
這也可以說是一個C++的值得商討的地方吧,不過更多的,這可以做一個好的特性來使用,因為它避免了一些有爭議的名稱解析。
你可以這樣指明調用關係:d.base::func(1);

derive類中的func關沒有覆蓋基類的虛函數。
思考如下的函數關係,你就會明白我說的爭議的名稱解析是什麼意思了。如果名稱尋找繼續發生在基類,後面的函數會引發二義性。
class base

{
public:
virtual void func(long a)
{
cout<<"reach base::func("<<a<<")"<<endl;
}

void func(double c)
{
cout<<"reach base::func("<<c<<")"<<endl;
}
};
class derive:public base
{
public:
virtual void func(long a)
{
cout<<"reach derive::func("<<a<<")"<<endl;
}
};

void main()
{
derive d;
d.func(1);
}
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.