c ++继承和共享指针

时间:2017-03-13 08:53:38

标签: c++ inheritance shared-ptr

情况如下。假设我们有一个虚基类(例如ShapeJuggler),它包含一个方法,该方法将一个指向虚基类对象(例如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似乎没有完成这项工作。 它可能吗?有什么想法,建议吗? 感谢

2 个答案:

答案 0 :(得分:4)

这是std::dynamic_pointer_cast(或其中一位朋友)发挥作用的地方 它就像dynamic_cast,但对于std::shared_ptr s。

在你的情况下(假设Shape类是多态的,所以dynamic_cast有效):

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

    sq->squareSpecificStuff();
}

答案 1 :(得分:3)

这是多个调度问题。他们是这个问题的很多解决方案,最干净的可能是使用访问者模式,但如果你只有一个需要多个调度的函数,你可以避免使用访问者:< / p>

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定义为final,这将启用一些虚拟化优化。