以前,看到 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; bp->f( 15 ); // BetterDerived::f_i(int) called bp->f( 1.5f ); // BetterBase::f_f(float) called } |
嗯~
這樣做起來的確好多了
但是…
換個角度想,好像把程式更複雜化了 囧
來源: 覆載(Override)、隱藏(Hiding)、與多載(Overloading)