2017-03-13 18 views
1

ここに状況があります。仮想基本クラス(たとえばShapeJuggler)に、仮想基本クラスオブジェクト(たとえばShape)への共有ポインタを引数として取り込むメソッドが含まれているとします。C++継承と共有ポインタ

class Shape { 
} 
class ShapeJuggler { 
    virtual void juggle(shared_ptr<Shape>) = 0; 
} 
// Now deriving a class from it 
class Square : public Shape { 
} 
class SquareJuggler : public ShapeJuggler { 
public: 
    void juggle(shared_ptr<Shape>) { 
     // Want to do something specific with a 'Square' 
     // Or transform the 'shared_ptr<Shape>' into a 'shared_ptr<Square>' 
    } 
} 
// Calling the juggle method 
void main(void) { 
    shared_ptr<Square> square_ptr = (shared_ptr<Square>) new Square(); 
    SquareJuggler squareJuggler; 
    squareJuggler.juggle(square_ptr); // how to access 'Square'-specific members? 
} 
make_shared

またはダイナミック/ static_castを仕事をしていないように見えます:理解するには、以下の疑似コードに飛び込むのをしてみましょう。 それはすべて可能ですか?任意のアイデア、提案?
ありがとう

+1

'main()'は 'void'ではなく' int'を返すべきです。 –

+0

"_weは仮想基底クラスを持っています_"あなたの例(または "擬似コード")に**仮想**キーワードを忘れました – curiousguy

答えて

4

これはstd::dynamic_pointer_cast(またはその友人の1人)が出場する場所です。
ちょうどdynamic_castのようですが、std::shared_ptrの場合です。これは多重ディスパッチ問題である

void juggle(shared_ptr<Shape> shape) { 
    auto const sq = std::dynamic_pointer_cast<Square>(shape); 
    assert(sq); 

    sq->squareSpecificStuff(); 
} 
3

:あなたのケースでは

Shapeクラスを想定したのでdynamic_cast作品多型です)。彼らのこの問題に対する多くの解決策、クリーンはビジターパターンを使用している場合がありますがありますが、あなただけの複数の派遣を必要とする一つの機能を持っている場合は、訪問者の使用を避けることができます:

class SquareJuggler; 
class TriangleJuggler; 
//.... others concrete jugglers. 

class Shape { 
    //The default behaviour for any juggler and any shape 
    virtual void juggle_by(Juggler& t) { 
     //default code for any shape an juggle 
    } 
    // list each juggler for which you may 
    // implement a specific behavior 
    virtual void juggle_by(SquareJuggler& t) { 
     //provides default behavior in case you will not 
     // create a specific behavior for a specific shape. 
     //for example, just call the unspecific juggler: 
     this->Shape::juggle_by(static_cast<Juggler&>(t)); 
    } 
    virtual void juggle_by(TriangleJuggler& t) { 
     //provides default behavior in case you will not 
     //create a specific behavior for a specific shape. 
     //for example, just call the unspecific juggler: 
     this->Shape::juggle_by(static_cast<Juggler&>(t)); 
    } 
    //... 
}; 
// Now deriving a class from it 
class Square : public Shape { 
    void juggle_by(SquareJuggler& s) override{ 
    //code specific to SquareJuggler and Shape 
    } 
}; 
class Triangle : public Shape { 
    void juggle_by(TriangleJuggler& t) override{ 
    //code specific to TriangleJuggler and Shape 
    } 
}; 

class ShapeJuggler { 
    virtual void juggle(shared_ptr<Shape> s) { 
    //by default (if default has sense): 
    s->juggle_by(*this); 
    } 
}; 
class SquareJuggler: public ShapeJuggler { 
public: 
    void juggle(shared_ptr<Shape> s) override { 
     s->juggle_by(*this); 
    } 
}; 
class TriangleJuggler: public ShapeJuggler { 
public: 
    void juggle(shared_ptr<Shape> s) override { 
     s->juggle_by(*this); 
    } 
}; 
// Calling the juggle method 
void main(void) { 
    shared_ptr<Square> square_ptr = (shared_ptr<Square>) new Square(); 
    SquareJuggler squareJuggler; 
    squareJuggler.juggle(square_ptr); 
     //This last call, will perform two virtual calls: 
     // 1. SquareJuggler::juggle(shared_ptr<Shape); 
     // 2. Square::juggle_by(SquareJuggler&); 
} 

あなたは可能性も定義あなたのXXXJugglerを最終的なものにしてください。

+0

この非常に完全で明確な説明を提供していただきありがとうございます。 –