? asked in 電腦與網際網路程式設計 · 2 decades ago

何謂double dispatching

我們在作剪刀 石頭 布的時候有用到

可是不大了解他的涵義耶

2 Answers

Rating
  • 2 decades ago
    Best Answer

    你是要問如何實作 C++ 裡的 double dispatching 吧!

    double dispatching 是一種概念,也可以說是一種小技巧。它主要是要解決以下這種類型的問題:

    一個 superclass Printer,二個 subclass InkjetPrinter 和 PostscriptPrinter。

    另外有一個 superclass Figure,二個 subclass Circle 和 Rectangle

    利用這些 class 的宣告,希望執行下列的動作。

    // 可能傳回 InkjetPrinter 和 PostscriptPrinter 的物件

    Printer *p = getPrinter();

    // 可能傳回 Circle 和 Rectangle 的物件

    Figure *f = getFigure();

    // 希望能呼叫個別 Circle 或 Rectangle 的 method,然後透過不同的

    // Printer subclass 去列出東西來

    f->printOn(p);

    要讓以上這些程式片段達到我們的目的是需要一些技巧的。因為在 C++ 裡,呼叫者的型別 (在本例中是 f) 是動態決定的。所以如果 getFigure() 傳回的是 Circle 這種 class 的 object ,那麼執行 f->PrinterOn(p),就會執行到 Circle 裡定義的 PrinterOn()。所以呼叫者這部份沒有問題。

    但是,C++裡參數型別是在編譯時期(compile time)就決定好的。在編譯時期,編譯器只知道 p 的型別是 Printer。而不知道是 InkjetPrinter 還是 PostscriptPrinter。

    為了達到我們的目的,在寫作上就要像以下這樣

    class InkjetPrinter : public Printer {

    public:

    void printCircle(const Circle *circle) {

    // ... rasterizing logic for inkjet printing of circles here ...

    cout << "Inkjet printer prints a circle." << endl;

    }

    void printRectangle(const Rectangle *rectangle) {

    // ... rasterizing logic for inkjet printing of rectangles here ...

    cout << "Inkjet printer prints a rectangle." << endl;

    }

    };

    class PostscriptPrinter : public Printer {

    public:

    void printCircle(const Circle *circle) {

    // ... postscript preprocessing logic for circles here ...

    cout << "PostScript printer prints a cirlce." << endl;

    }

    void printRectangle(const Rectangle *rectangle) {

    // ... postscript preprocessing logic for rectangles here ...

    cout << "PostScript printer prints a rectangle." << endl;

    }

    };

    class Circle : public Figure {

    public:

    void printOn(Printer* printer) {

    printer->printCircle(this); // <-- 此處為關鍵技巧

    }

    };

    class Rectangle : public Figure {

    public:

    void printOn(Printer* printer) {

    printer->printRectangle(this); // <-- 此處為關鍵技巧

    }

    };

    請留意註解中有寫"此處為關鍵技巧"那兩行。

    既然「呼叫者」的型別是動態決定的。那我們將參數再當成呼叫者去執行它的成員函式,就可以解決參數型別的限制。所以你可以看到上面的例子裡將 printer 當成呼叫者,再去執行它的成員函式。但是它的參數還是要是 Figure 這種型別才行啊,那會不會又遇到前面參數型別不法動態決定的問題。這個函式因為是 Circle 或 Rectangle 的成員函式,所以可以用 this 來代表目前動態的型別為何。

    以上的方法中,f->printOn(p) 就是 first dispatching。而將傳入的參數當 caller ,printer->printRectangle(this) 或 printer->printCircle(this),就是所謂的 second dispatching。因此這種作法就叫 double dispatching

  • Anonymous
    2 decades ago

    多次改變原理

    它不是組合的因為你不能只有單項記錄

    它是每次把為第二份、三份...等類型也記錄下來

    操作的項目是相等的或與組合性(數量實際 操作的總數量)

    Source(s): 學的
Still have questions? Get your answers by asking now.