ダブル・ディスパッチを書いてみる

意識しないで使ってそうだが、ダブル・ディスパッチ~ 典型的なオブジェクト指向プログラミング・イディオム ~にあるダブル・ディスパチをC++でメモっておく。
これは要するにif-else or switch的な処理で書いてしまいそうな所を、あるメソッド数呼び出しの中で自身を引数として別な関数を呼び出す事で回避するテクニック。

#include<iostream>
//前方宣言
class Member;
class CD;
class DVD;

//Member系
class Member
{
public:
    virtual int calculateRentalFeeForCD(CD & item) = 0;
    virtual int calculateRentalFeeForDVD(DVD & item) = 0;
};
class CommonMember : public Member
{
public:
    int calculateRentalFeeForCD(CD & item){return 100;} 
    int calculateRentalFeeForDVD(DVD & item){return 300;} 
};
class GoldMember : public Member
{
public:
    int calculateRentalFeeForCD(CD & item){return 99;} 
    int calculateRentalFeeForDVD(DVD & item){return 100;} 
};

//Item系
class Item
{
public:
    virtual int calculateRentalFee(Member & member) = 0;
};
class CD : public Item
{
public:
    int calculateRentalFee(Member & member){return member.calculateRentalFeeForCD(*this);}
};
class DVD : public Item
{
public:
    int calculateRentalFee(Member & member){return member.calculateRentalFeeForDVD(*this);}
};

//メイン
int main()
{
    CommonMember common;
    GoldMember gold;
    CD cd;
    DVD dvd;
    std::cout << "Member:Common, Item:CD,  Fee:" << cd.calculateRentalFee(common) << std::endl;
    std::cout << "Member:Gold,   Item:CD,  Fee:" << cd.calculateRentalFee(gold) << std::endl;
    std::cout << "Member:Common, Item:DVD, Fee:" << dvd.calculateRentalFee(common) << std::endl;
    std::cout << "Member:Gold,   Item:DVD, Fee:" << dvd.calculateRentalFee(gold) << std::endl;
    return 0;
}

実行結果

Member:Common, Item:CD,  Fee:100
Member:Gold,   Item:CD,  Fee:99
Member:Common, Item:DVD, Fee:300
Member:Gold,   Item:DVD, Fee:100