user1156770
user1156770

Reputation:

How shall I use derived classes with vectors and shared pointers?

I am not familiar with the concept of inheritance, and I am struggling to find a solution to the following problem.

I have 2 classes, Head and Hand. I use instances of these classes mostly as elements of a vector. The two classes have methods in common and methods peculiar only to them.

Moreover, I deal with shared pointers of the object.

I thought the best way to implement it was to create a class BodyPart, like this

class BodyPart
{
  public:
  typedef boost::shared_ptr<BodyPart> pointer;

  private:
  int commonMember1;
  double commonMember2;

  public:
  int commonMethod1();
  int CommonMethod2();
}

and the two derived classes like this

class Hand : public BodyPart
{
  public:
  typedef boost::shared_ptr<Hand> pointer;

  private:
  int numFingers;

  public:
  int getNumFingers();
  void printInfo();
}

Finally, I wanted to declare a vector of BodyPart elements:

std::vector<BodyPart::pointer> cBodyParts;

containing either Hand or Head elements, and call my methods on the vector elements when I need.

But this approach doesn't seem to work very well. Apparently, when I try to get an element of the vector, the compiler complains that it cannot convert from a BodyPart shared pointer to a Hand shared pointer. Moreover, if the vector is declared like above, I cannot call methods specific to the derived classes (like getNumFinger() ) on its element, even if the actually are from that class.

Is there a proper way to deal with this? Or is my approach completely wrong? Thanks in advance!

Upvotes: 2

Views: 897

Answers (2)

Luchian Grigore
Luchian Grigore

Reputation: 258678

Your approach is correct, but so is the compiler. It's good that you have a vector of shared pointers to the base class, but you'll need to cast to the actual type to get specific functionality.

The typedef boost::shared_ptr<Hand> pointer; is useless though, you only need the typedef in the base class. You won't be casting between smart pointers. I'd rename the base class typedef to

typedef boost::shared_ptr<BodyPart> BodyPartPtr;

though.

Good point by Alan in the comments: you should make the base class's destructor virtual to prevent UB, since you'll be deleting (indirectly) pointers to derived types through a pointer to a base type.

Upvotes: 3

Qortex
Qortex

Reputation: 7466

Your approach is right (though you don't really need the typedef), you just need to use boost::static_pointer_cast (Doc here) to convert from shared_ptr<BodyPart> to shared_ptr<Hand> when you need it.

You may also have a look at enable_shared_from_this at some point in your learning.

Upvotes: 2

Related Questions