c++ 继承和共享指针
c++ Inheritance and shared pointers
情况是这样的。假设我们有一个虚拟基 class(例如 ShapeJuggler
),它包含一个方法,该方法将指向虚拟基 class 对象(例如 Shape
)的共享指针作为参数。让我们跳入下面的伪代码来理解:
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 或 dynamic/static_cast 似乎无法完成这项工作。
有可能吗?有什么想法、建议吗?
谢谢
这就是 std::dynamic_pointer_cast
(或其朋友之一)发挥作用的地方。
就像 dynamic_cast
,但是 std::shared_ptr
s.
在你的情况下(假设 Shape
class 是多态的,所以 dynamic_cast
有效):
void juggle(shared_ptr<Shape> shape) {
auto const sq = std::dynamic_pointer_cast<Square>(shape);
assert(sq);
sq->squareSpecificStuff();
}
这是多重分派问题。他们有很多解决这个问题的方法,最干净的可能是使用 visitor 模式,但是如果你只有一个函数需要 multiple dispatch 你可以避免使用访客:
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 定义为最终的,这将启用一些去虚拟化优化。
情况是这样的。假设我们有一个虚拟基 class(例如 ShapeJuggler
),它包含一个方法,该方法将指向虚拟基 class 对象(例如 Shape
)的共享指针作为参数。让我们跳入下面的伪代码来理解:
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 或 dynamic/static_cast 似乎无法完成这项工作。
有可能吗?有什么想法、建议吗?
谢谢
这就是 std::dynamic_pointer_cast
(或其朋友之一)发挥作用的地方。
就像 dynamic_cast
,但是 std::shared_ptr
s.
在你的情况下(假设 Shape
class 是多态的,所以 dynamic_cast
有效):
void juggle(shared_ptr<Shape> shape) {
auto const sq = std::dynamic_pointer_cast<Square>(shape);
assert(sq);
sq->squareSpecificStuff();
}
这是多重分派问题。他们有很多解决这个问题的方法,最干净的可能是使用 visitor 模式,但是如果你只有一个函数需要 multiple dispatch 你可以避免使用访客:
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 定义为最终的,这将启用一些去虚拟化优化。