2017-03-13 3 views
1

Hier ist die Situation. Angenommen, wir haben eine virtuelle Basisklasse (z. B. ShapeJuggler), die eine Methode enthält, die einen gemeinsamen Zeiger auf ein virtuelles Basisklassenobjekt (z. B. Shape) als Argument verwendet. Lassen Sie sich in den folgenden Pseudo-Code springen zu verstehen:C++ Vererbung und gemeinsame Zeiger

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 oder dynamisch/static_cast scheint nicht den Job zu erledigen. Ist es überhaupt möglich? Irgendwelche Ideen, Vorschläge?
Danke

+1

'main()' sollte 'int' zurückgeben, nicht' void'. –

+0

"_Wir haben eine virtuelle Basisklasse_" Sie haben das ** virtuelle ** Schlüsselwort in Ihrem Beispiel (oder "Pseudocode") vergessen – curiousguy

Antwort

4

Hier kommt std::dynamic_pointer_cast (oder einer seiner Freunde) ins Spiel.
Es ist wie dynamic_cast, aber für std::shared_ptr s.

In Ihrem Fall (die Shape Klasse unter der Annahme, so dynamic_cast Werke polymorphe):

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

    sq->squareSpecificStuff(); 
} 
3

Dies ist das mehr Dispatch Problem. Ihr sind viele Lösung für dieses Problem, das sauberste die Besuchermuster verwenden könnte, aber wenn Sie nur eine Funktion, die mehrere Dispatch müssen Sie mit einem Besucher vermeiden könnte:

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&); 
} 

Sie könnten auch definiert Dein XXXJuggler als final, was einige Devirtualisierungs-Optimierungen ermöglicht.

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, diese sehr vollständige und klare Erklärung zu geben. –