[翻譯] Effective C++, 3rd Edition, Item 33: 避免覆蓋(hiding)“通過繼承得到的名字”(下)

來源:互聯網
上載者:User

(點擊此處,接上篇)

這一行為背後的根本原因是為了防止“當你在一個 library 或者 application framework 中建立一個新的 derived class 時,偶然地發生從遙遠的 base classes 繼承 overloads 的情況”。不幸的是,一般情況下你是需要繼承這些 overloads 的。實際上,如果你使用了 public inheritance 而又沒有繼承這些 overloads,你就違反了 Item 32 講解的“base 和 derived classes 之間是 is-a 關係”這一 public inheritance 的基本原則。在這種情況下,你幾乎總是要繞過 C++ 對“通過繼承得到的名字”的預設的覆蓋機制。

你可以用 using declarations 做到這一點:

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;       // make all things in Base named mf1 and mf3
  using Base::mf3;       // visible (and public) in Derived's scope

  virtual void mf1();
  void mf3();
  void mf4();
  ...
};

 

現在 inheritance 就可以起到預期的作用:

Derived d;
int x;

...

d.mf1();                 // still fine, still calls Derived::mf1
d.mf1(x);                // now okay, calls Base::mf1

d.mf2();                 // still fine, still calls Base::mf2

d.mf3();                 // fine, calls Derived::mf3
d.mf3(x);                // now okay, calls Base::mf3

這意味著如果你從一個帶有重載函數的 base class 繼承,而且你只想重定義或替換它們中的一部分,你需要為每一個你不想覆蓋的名字使用 using declaration。如果你不這樣做,一些你希望繼承下來的名字會被覆蓋。

可以想象在某些時候你不希望從你的 base classes 繼承所有的函數。在 public inheritance 中,這是絕不會發生的,這還是因為,它違反了 public inheritance 在 base 和 derived classes 之間的 is-a 關係。(這就是為什麼上面的 using declarations 在 derived class 的 public 部分:在 base class 中是 public 的名字在公有繼承的 derived class 中也應該是 public。)然而,在 private inheritance(參見 Item 39)中,它還是有意義的。例如,假設 Derived 從 Base 私人繼承,而且 Derived 只想繼承沒有參數的那個 mf1 的版本。在這裡,using declaration 沒有這個本事,因為一個 using declaration 會使得所有具有給定名字的函數在 derived class 中可見。不,這裡是使用了一種不同的技術的情形,即,一個簡單的 forwarding function(轉調函數):

class Base {
public:
  virtual void mf1() = 0;
  virtual void mf1(int);

  ...                                    // as before
};

class Derived: private Base {
public:
  virtual void mf1()                   // forwarding function; implicitly
  { Base::mf1(); }                     // inline (see Item 30)
  ...
};

...

Derived d;
int x;

d.mf1();                               // fine, calls Derived::mf1
d.mf1(x);                              // error! Base::mf1() is hidden

forwarding function(轉調函數)的另一個功效是用於老式的編譯器,它們(不正確地)不支援用 using declarations 將“通過繼承得到的名字”引入到 derived class 的範圍。

這就是關於 inheritance 和 name hiding 的全部故事,但是當 inheritance 與 templates 結合起來,“通過繼承得到的名字被隱藏”的問題會以一種全然不同的形式呈現出來。關於全部 angle-bracket-demarcated(邊邊角角)的細節,參見 Item 43。

Things to Remember

  • derived classes 中的名字覆蓋 base classes 中的名字,在 public inheritance 中,這從來不是想要的。
  • 為了使隱藏的名字重新可見,使用 using declarations 或者 forwarding functions(轉調函數)。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.