設計模式:多重派遣,設計模式派遣
在物件導向程式設計中,非常常用的手法就是用基類的指標指向衍生類別,然後在執行期通過虛函數機制找到衍生類別中的函數,假設這樣一種情況,全域函數有兩個輸入參數,分別是兩個基類指標 A* ap 和 B* bp,那麼如何既找到ap指向的準確對象,又找到bp指向的準確對象呢?答案就是多重派遣,既先找到ap(bp)指向的準確對象,再去尋找bp(ap)指向的準確對象,程式碼範例如下:
#include <iostream>using namespace std;class A {public:virtual void funca() { cout<<"Base A"<<endl; }};class A1 : public A {public:void funca() { cout<<"Derived A1"<<endl; }};class A2 : public A {public:void funca() { cout<<"Derived A2"<<endl; }};class B {public:virtual void funcb(A *p) { cout<<"Base B"<<endl; p->funca();}};class B1 : public B {public: void funcb(A *p) { cout<<"Derived B1"<<endl; p->funca();}};class B2 : public B {public:void funcb(A *p) { cout<<"Derived B2"<<endl; p->funca();}};void func(A *a, B* b) { b->funcb(a); }int main(){B *bp = new B1();A *ap = new A1();func(ap,bp);return 0;}
在上面的例子中,func(A*, B*)就是前面所說的全域函數,最後通過兩層虛函數調用將ap和bp指向正確的衍生類別對象。當然,實現多重派遣不只這一種方法,也可以通過重載的方式來實現,如下:
class B {public:void funcb(A *p) { cout<<"Base B"<<endl; cout<<"Base A"<<endl;;}void funcb(A1 *p) { cout<<"Base B"<<endl; cout<<"Derived A1"<<endl;}void funcb(A2 *p) { cout<<"Base B"<<endl; cout<<"Derived A2"<<endl;}};在這種情況下,B需要知道A有哪些衍生類別,然後為A的每一個衍生類別定義一個函數的重載版本,在A中可以通過將this指標傳遞給對B的調用,如下:
class A {public:virtual void funca(B *p) { p->funcb(this);}};class A1 : public A {public:void funca(B *p) { p->funcb(this); }};class A2 : public A {public:void funca(B *p) { p->funcb(this);}};全域函數的定義如下:
void func(A *ap, B* bp) { ap->funca(bp); }這樣首先通過虛函數調用找到了A的衍生類別對象,然後在A的衍生類別對象中將this指標傳給對B的調用,而此時傳進去的this指標已經是衍生類別的指標,所以可以協助B選擇正確的函數重載版本。