多重繼承(二)


多重繼承時通常其中一個基底類別作為private實作體,而其它的用以表現完全的抽象介面。

考慮您有一個方法doRequest(),您事先並無法知道什麼型態的物件會被傳進來,或者是這個方法可以接受任何類型的物件,您想要操作物件上的某個特 定方法,例如doSomething()方法,問題是傳進來的物件是任意的,除非您定義一個抽象類別並宣告doSomething()抽象方法,然後讓所 有的類別都繼承這個抽象類別,否則的話您的doRequest()方法似乎無法實作出來,實際上這麼作也沒有價值。

您可以藉由多重繼承來解決這個問題,例如先定義一個抽象類別:
  • IRequest.h
#ifndef IREQUEST
#define IREQUEST

class IRequest {
public:
virtual void execute() = 0;
};

#endif

假設您的類別是以下的SomeObject類別的子類別:
  • SomeObject.h
#ifndef SOMEOBJECT
#define SOMEOBJECT

#include <iostream>
using namespace std;

class SomeObject {
public:
virtual void someFunction() {
cout << "do something" << endl;
}

private:
void otherFunction() {
cout << "do other" << endl;
}
};

#endif

為了滿足之前所提供的doRequest()的需求,您讓衍生類別同時繼承IRequest與SomeObject類別,例 如:
  • Welcome.h
#include "IRequest.h"
#include "SomeObject.h"
#include <iostream>
using namespace std;

class Welcome : public SomeObject, public IRequest {
public:
void execute() {
cout << "Welcome!!" << endl;
}
};
  • Hello.h
#include "IRequest.h"
#include "SomeObject.h"
#include <iostream>
using namespace std;

class Hello : public SomeObject, public IRequest {
public:
void execute() {
cout << "Hello!!" << endl;
}
};

假設您設計了一個doRequest()方法,雖然不知道Hello與 Welcome是什麼型態,但它們 都繼承了IRequest,所以doRequest()只要知道IRequest定義了什麼公開介面,就可以操作Hello與Welcome的實例,而不 用知道傳入的物件到底是什麼類別的實例,使用下面這個程式來測試:
  • main.cpp
#include <iostream> 
#include "IRequest.h"
#include "Welcome.h"
#include "Hello.h"
using namespace std;

void doRequest(IRequest *request) {
request->execute();
}

int main() {
Welcome welcome;
Hello hello;

doRequest(&welcome);
doRequest(&hello);

return 0;
}

執行結果:

Welcome!!
Hello!!