2017-03-13 2 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 (또는 친구 중 한 명)이 참가하는 곳입니다.
과 같지만, std::shared_ptr은 0입니다.

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

이 매우 완전하고 명확한 설명을 해주셔서 감사합니다. –