2

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!

  • I'm not sure what the usefulness of the repeated `pointer` subtype is here. I would use regular inheritance, and have an `std::vector>`. Tuck the shared pointer in a typedef if desired, I suppose. – WhozCraig Jan 04 '13 at 13:05

2 Answers2

3

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.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • +1 and yeah, nice to see someone using smart pointers right from the start for a change. Wish there was more of that. – WhozCraig Jan 04 '13 at 13:06
  • 1
    Its worth pointing out that you should make your base class destructor virtual if you are storing pointers to the base class rather than the derived ones. – Alan Jan 04 '13 at 13:15
  • Great, thanks for the clarification! @Alan: I made the base class destructor virtual, I just omitted to show it in the question for the sake of simplicity. Good point, though :-) –  Jan 04 '13 at 14:02
2

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.

Community
  • 1
  • 1
Qortex
  • 7,087
  • 3
  • 42
  • 59