ダブルディスパッチ

なにやら難しい言葉だがやってる事は簡単である。

struct Zaku{};
struct Char_zaku
    : public Zaku{};

struct Gundam{
    void say(const Zaku&) const{
        std::cout << "相手がザクなら!人間じゃないんだ、ぼくだって" << std::endl;
    }
    void say(const Char_zaku&) const{
        std::cout << "撃つぞ・・・撃つぞ・・・撃つぞぉぉぉ!" << std::endl;
    }
};

引数の型によって処理を変更したい場合があるとする。
呼び出し側は以下のようになる。

Zaku          zaku;
Char_zaku     char_zaku;
Gundam        gundam;

gundam.say(zaku);         // Gundam::say(const Zaku&) が呼ばれる
gundam.say(char_zaku);    // こっちも問題なく呼び出される

つまり、ダブルディスパッチとは、実行時の型によって異なる関数を呼び出す為の機構である。
C++だと関数のオーバーロードを利用して行っている。
よく理解していなかったので改めて調べてみたら単なるバズワードだった。


また、以下のような場合には注意が必要である。

Zaku&         zaku = Char_zaku();
Gundam        gundam;

gundam.say(zaku);  // Gundam::say(const Zaku&) が呼ばれる      
                   // 本当は Gundam::say(const Char_zaku&) が呼ばれて欲しい

この場合は、自分を渡すような処理を追加して対応する。

struct Zaku{
    virtual void call_say(const Gundam& gundam){
        gundam.say(*this);
    }
};

struct Char_zaku
    : public Zaku{
    virtual void call_say(const Gundam& gundam){
        gundam.say(*this);
    }
};
Zaku&        zaku = Char_zaku();
Gundam        gundam;

zaku.call_say(gundam);    // 問題なく Gundam::say(const Char_zaku&) が呼ばれる

これで問題なく呼ばれる。

続く…?