2011-10-26 15 views
0

次のC++での多態性の例を考えてみましょう。私にとって、これは予期せぬ動作であり、おそらくまだ私はJavaであまりにも多くのことを考えているということにあります。私にとっての質問は、今、より具体的なメソッドを呼び出すポインタの例を取得する方法です。ポインタを持つ多型:: boost :: shared_ptr

#include <iostream> 
#include <string.h> 
#include <boost/tr1/memory.hpp> 

class Image { 
public: 
    Image(std::string className = "Image") 
     : className_(className) 
    {} 

    virtual ~Image() {} 

    virtual std::string className() { 
    return className_; 
    } 

private: 
    std::string className_; 
}; 

class RightImage : public Image { 
public: 
    RightImage() 
     : Image("RightImage") 
    {} 
}; 

class Processor{ 
public: 
    void process(Image& image){ 
    std::cout << "Invoking process(Image& image) with image of type \"" << image.className() << "\"" << std::endl; 
    } 
    void process(RightImage& rightImage){ 
    std::cout << "Invoking process(RightImage& rightImage) with rightImage of type \"" << rightImage.className() << "\"" << std::endl; 
    } 

    void process(Image* image){ 
    std::cout << "Invoking process(Image* image) with image of type \"" << image->className() << "\"" << std::endl; 
    } 
    void process(RightImage* rightImage){ 
    std::cout << "Invoking process(RightImage* rightImage) with rightImage of type \"" << rightImage->className() << "\"" << std::endl; 
    } 
}; 

int main(int argc, char **argv) { 
     std::tr1::shared_ptr<Image> rightImageSharedPtr(new RightImage()); 
     Image* rightImagePointer = new RightImage(); 
     RightImage rightImage; 
     Processor processor; 
     std::cout << "value:     "; 
     processor.process(rightImage); 
     std::cout << "shared_ptr:    "; 
     processor.process(*rightImageSharedPtr); 
     std::cout << "old fashioned pointer 1: "; 
     processor.process(*rightImagePointer); 
     std::cout << "old fashioned pointer 2: "; 
     processor.process(rightImagePointer); 
} 

そのプログラムの出力は次のとおり起動プロセス(画像&画像)と:

値:タイプ "RightImage"

のshared_ptrのrightImageと起動プロセス(RightImage & rightImage)タイプ「RightImage」の画像

旧式のポインタ1:画像を呼び出す処理(画像&画像)タイプ「RightImage」

昔ながらのポインタ2:タイプのイメージと起動プロセス(画像*画像)「RightImage」

は、どのように私は最後の3例もprocess(RightImage&)process(RightImage*)を呼び出すことができますか?あなたは

std::tr1::shared_ptr<RightImage> rightImageSharedPtr(new RightImage()); 
    RightImage* rightImagePointer = new RightImage(); 

代替のちょうどより複雑な方法である各関数を呼び出す前にはdynamic_castを実行することであるとして、あなたの変数を宣言する必要があるので、

+0

これはJavaで動作するはずですか? – curiousguy

+0

@curiousguyいいえ、そうではありません。しかしJavaでは、リフレクションを使用してクラスタイプを取得することができました;-) – sebastiangeiger

答えて

1

tokageが提案しているように、Process()関数内に基本クラスの仮想関数を呼び出すことによって、多相を使用することもできます。

+0

例で説明した方法では訪問者のパターンが必要になるでしょうが、私の具体的な問題では仮想の 'process()'関数'Image'クラスと多態性を使用しています。 – sebastiangeiger

0

オーバーロードは、関数の引数の静的な型に解決されます同じことをやっている。

+0

理想的には 'Image'が私のインターフェースになり、処理のためにSubtypeを渡すので、これは私のデザインには正確には当てはまりません。 – sebastiangeiger

+1

@sebastiangeiger:あなたの設計であれば、サブタイプのための別個のオーバーロードを*持たないでください。すべてが共通のインターフェースを通じて行われるべきです。 –

1

私はあなたの問題を解決するためにダブルディスパッチ/ビジターパターンのようなものが欲しいと思います。

あなたのイメージを実際にインターフェイスの下に置いている情報は、オブジェクト内でのみ利用可能です。そのため、イメージオブジェクトの仮想メソッドを呼び出して、基になる型を取得する必要があります。

例:もちろん

class Image{ 
    virtual void process(Processor &processor)=0; 
} 

class RightImage{ 
    virtual void process(Processor &processor){ 
     processor.process(this); 
    } 
} 

あなたも()プロセスで画像クラス内の処理を行うことができます - 方法を、私はあなたがプロセッサの種類が異なるタイプの画像に仕事をしたいと思います。 もう1つの選択肢は、おそらく少し洗練されたものですが、画像タイプごとに異なる単一の処理ステップの仮想メソッドをプロセッサに呼び出させることです。

+0

私はビジターパターンのアイディアを自分で持っていたはずです:-) – sebastiangeiger

関連する問題