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

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

把設計風格改成大量的多載(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) 虛擬函式
嗯~這裡是本篇最重要的點
首先,先來看直覺的作法,也就是我看到這篇之前的作法
同樣是引用的~

 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)

–End

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s