1

覆載(Override)、隱藏(Hiding)、與多載(Overloading)

 2 years ago
source link: https://fredxxx123.wordpress.com/2007/12/10/%e8%a6%86%e8%bc%89override%e3%80%81%e9%9a%b1%e8%97%8fhiding%e3%80%81%e8%88%87%e5%a4%9a%e8%bc%89overloading/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

覆載(Override)、隱藏(Hiding)、與多載(Overloading)

以前,看到 Override 和 Overloading 一直似懂非懂的
至於隱藏(Hiding)倒是第一次看到…
今天把物件加入 Node 機制,順便整理一下目前寫過的物件
重新設計某些環節時,看著無數個 SetXxx 和 GetXxx
一整個気持ち就不好y14.gif

把設計風格改成大量的多載(Overloading)取代 SetGet 地獄
雖然使用起來不一定比較好用,但是看起來比較順眼,哈哈
當然有些問題就孑然而生,拜辜狗找到這些資料
OK~回正題

以下直接引用~
覆載(Override)
配合繼承架構,衍生類別的虛擬函式可以取代基礎類別的同名虛擬函式
運用多型指標時虛擬函式呼叫可以動態地繫結(bind)到該物件的虛擬函式上
例如:

 class Base {
 public:
     virtual void service( ) { };
 };   class Derived: public Base {
 public:
     void service( ) { };
 };  void main( ) {
     Derived dObj;
     Base *bPtr = &dObj;
     bPtr->service( );
 }

多載(Overloading)
在同一個命名區間(name space)中兩個函式有同樣的名稱
但是具有不同的參數個數或是參數型態的稱為多載函式
例如:

 class Base {
 public:
     virtual void service( ) { };
     virtual void service( int x ) { };
 };   void main( ) {
     Base bObj;
     bObj.service( );
     bObj.service( 10 );
 }

上例中兩個函式可以是虛擬函式或是一般的函式,

不同的類別(包括繼承時的父類別及子類別)是不同的 name space,父類別與子類別之間的函式沒有 overload 的關係。

隱藏(Hiding)
在繼承架構中,衍生類別的界面除了自己定義的界面之外
還包括所有基礎類別裡所定義的界面
但是當衍生類別中定義一個和基礎類別中同名的函式時
基礎類別中那個同名的函式(不管它的參數是不是一樣)就會被隱藏起來
透過衍生類別的指標或是物件參考都沒有辦法直接呼叫到
例如:

 class Base {
 public:
     virtual void service( ) { };
 };  class Derived: public Base {
 public:
     virtual void service( int  ) { };
 };  void main( ) {
     Derived dObj;
     Derived *dPtr = &dObj;
     Base *bPtr = &dObj;
     dObj.service( 10 );
     dObj.service( ); // compile time error, hiding
     dObj.Base::service( ); // OK
     dPtr->service( 10 );
     dPtr->service( ); // compile time error, hiding
     dPtr->Base::service( ); // OK
     bPtr->service( ); // OK
     bPtr->service( 10 ); // compile time error
 }

hiding 的現象和是否為虛擬函式,函式的存取權限,或是函式的參數都沒有關係,只要衍生類別有一個同名的函式,所有基礎類別內的同名函式都不再能直接使用。

JAVA 中沒有提供 hiding 的功能,類別樹不同類別的所有的成員函式都可以自由地互相 overload

為什麼 C++ 要制定這樣子的 hiding 法則呢? 請參考底下連結
(還有一些重點在這不再贅述)

請不要多載 (overload) 虛擬函式
嗯~這裡是本篇最重要的點
首先,先來看直覺的作法,也就是我看到這篇之前的作法embaressed_smile.gif
同樣是引用的~

 class PoorBase {
 public:
     virtual void f( int x ) {}; // f is overloaded virutal functions
     virtual void f( float x ) {};
 };  class PoorDerived : public PoorBase { // PoorBase::f(float) is hidden
 public:
     virtual void f( int x ) {};
 };  class ModifiedDerived : public PoorBase {
 public:
     virtual void f( int x ) {};
     virtual void f( float x ) { PoorBase::f( x ); }
 };

其中 ModifiedDerived 是我本來要尋求的解決方法
但每次 override 都要重複無趣的動作,無聊又多一道出錯的程序
比較好的做法如下:

 class BetterBase {
 public:
     void f( int x ) { f_i( x ); }
     void f( float x ) { f_f( x ); }
 protected:
     virtual void f_i( int x ) {};
     virtual void f_f( float x ) {};
 };  class BetterDerived : public BetterBase {
 protected:
     virtual void f_i( int x ) {} // override BetterBase::f_i(int)
 };  void main( ) {
     PoorDerived pd;
     pd.f( 1.5f ); // PoorDerived::f(int) called, (int) coersion applied

     ModifiedDerived md;
     md.f( 1.5f ); // ModifiedDerived::f(float) called

     BetterDerived d;
     BetterBase *bp = &d;
     bp->f( 15 ); // BetterDerived::f_i(int) called
     bp->f( 1.5f ); // BetterBase::f_f(float) called
 }

嗯~
這樣做起來的確好多了
但是…
換個角度想,好像把程式更複雜化了 囧

來源: 覆載(Override)、隱藏(Hiding)、與多載(Overloading)

發佈於 2007/12/102012/05/08作者 fredxxx123分類 C++, 程 - 式 - 設 - 計


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK