0

I have a class A, which defines an empty function foo, among other things. Two subclasses inherit from A, AA and AB. Both of these override foo in different ways.

A separate class, C, needs to hold different instances of the subclasses, so I have defined a vector with a template of class A within it. The issue is, when I try to run foo by accessing the subclass from the vector in C, it runs the empty version of foo in A, rather than the overridden version from AA or AB.

How can I have a vector in C which can hold different instances of the subclasses and be able to run the overridden version of foo?


If you'd prefer to see the classes in code -

A

class A
{
public:
    A();
    foo() {}
};

AA

class AA : public A
{
public:
    AA();
    foo() { //does something else }
};

AB

class AB : public A
{
public:
    AB();
    foo() { //does a different something else }
};

C

class C
{
public:
    C();

private:
    std::vector<A> things;
};

From within C, if I try to run things.at(x).foo() it calls the foo from A, but I need to call the foo from the correct subclass.

Thanks for any advice you can give!

H. Din
  • 41
  • 5
  • What do you mean correct? Which one would be correct here `things[0].foo();`? – Yola Mar 24 '18 at 13:49
  • I mean that `things` should hold a mix of instances of AA and AB, so the overridden version of foo would be called from that class, whatever it may be, but instead it is being called from A – H. Din Mar 24 '18 at 13:52
  • Vectors of baseclass, that always begets the question whether slicing/truncation is taking place. Did you follow general guidelines and disable assignment and copying? – Ulrich Eckhardt Mar 24 '18 at 13:56

1 Answers1

2

You need to mark your base class functions as virtual. By default c++ methods are non-virtual so all your instances of foo() are completely separate methods which just happen to have the same name.

If you are using a modern compiler you should also mark your derived methods with override to get the compiler to check for you that you really are overriding a base class method.

You also can't store the objects by value in the vector, you need to store pointers, references, unique_ptr or shared_ptrs instead. If you store by value when you add an object to the vector it will be copied into a new object of type A

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • Thanks, you hit the nail on the head! I had to both change foo to a virtual function _and_ change things to hold pointers rather than objects. – H. Din Mar 24 '18 at 14:20