1. 程式人生 > >C++進階--程式碼複用 繼承vs組合

C++進階--程式碼複用 繼承vs組合

//############################################################################
/*
 * 程式碼複用: 繼承 vs 組合
 */

//繼承實現程式碼複用
class BaseDog {
   ...
   ... // 公共的操作
};

class BullDog : public BaseDog {
   ... // 呼叫公共操作,執行更多工
};

class ShepherdDog : public BaseDog {
   ... // 呼叫公共操作,執行更多工
};




// 組合實現程式碼複用

class ActivityManager {
   ... // 公共操作
};

class Dog {
   ...
};

class BullDog : public Dog {
   ActivityManager* pActMngr;  
   ... //  通過pActMngr呼叫公共操作
};

class ShepherdDog : public Dog {
   ActivityManager* pActMngr;
   ... // 通過pActMngr呼叫公共操作
};




/*
 * 程式碼複用: 組合優於繼承
 *
 * 1. 複用者和被複用者之間具有更少的程式碼耦合
 *    a. 子類自動繼承父類所有的公有成員
 *    b. 子類可以訪問父類的保護成員
 *       - 繼承破壞了封裝性
 */

/*
 * 2. 動態繫結
 *    a. 繼承在編譯時繫結
 *    b. 組合可以在編譯時繫結,也可以在執行時繫結
 */

class OutdoorActivityManager : public ActivityManager {...}

class IndoorActivityManager : public ActivityManager {...}


/*
 * 3. 靈活的程式碼結構
 *
 *    Dog             ActivityManager
 *
 *    BullDog         OutdoorActivityManager
 *    ShepherdDog     IndoorActivityManager
 *    ...             ...
 */


// 組合的例子:只從純虛類繼承
class ActivityManager {
   void eatBiscuit() { ... }
};

class Dog {
   ...
   virtual void eatBiscuit() = 0;
};

class BullDog : public Dog {
   ActivityManager* pActMngr;
   ...
   void eatBiscuit() { pActMngr->eatBiscuit(); }
};

class ShepherdDog : public Dog {
   ActivityManager* pActMngr;
   ... 
   void eatBiscuit() { pActMngr->eatBiscuit(); }
};