Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling subclass methods from superclass in a vector C++

I am trying to add a number of subclassed elements into a vector, iterate through them calling a overridden method and want it to call the overridden method where possible. However I have found that it appears to only be calling the superclass method.

I learnt Java and am unsure why it is doing this in C++. I have tried rewriting the code using a vector of pointers of the superclass and casting the pointer of the subclass to the superclass. Accessing this through pointers then works.

Ideally I dont want to have to put a list of pointers into the vector since then I have to manually delete each one (I believe?) to stop memory leaks since I will be creating the objects with new so they persist past the method call to add them into the vector.

Is there a better way to do this or am I stuck to using pointers and calling delete on the created objects when the parent class is unneeded? Preferably the vector would be a list of class X rather than a list of pointers of class X

My structure is:

class a { vector vec of class X,
    method to create and add an instance of X into vector vec,
    method to create and add an instance of Y into vector vec }
class X { talk() }
class Y : public X { talk() }

Code to demonstrate what I ideally want to do, but showing its broken by only calling the superclass method:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>

class A {
  public:
    virtual void talk() { printf("A\n"); }
};

class B: public A {
  public:
      void talk() { printf("B\n"); }
};

int main(void) {
    std::vector<A> vec;
    std::vector<A*> vec2;
    A a;
    B b;
    a.talk();
    b.talk();

    vec.push_back(a);
    vec.push_back(b);
    vec2.push_back(&a);
    vec2.push_back(&b);

    for(int i = 0; i < vec.size(); i++) {
        vec[i].talk();
        vec2[i]->talk(); //bad but short for example
    }

}
like image 848
Chewett Avatar asked Jul 19 '14 19:07

Chewett


1 Answers

To get the polymorphic behaviour you want you need to add the virtual specifier to the functions in the base class that you want to override in derived classes.

class A {
public:
    virtual void talk() { printf("A\n"); }
};

You should also make a habit of adding the override specifier on overridden functions in derived classes so that the compiler can help you with these kind of issues.

class B: public A {
public:
    virtual void talk() override { printf("B\n"); }
//                      ^ Compiler will report an error if base class' function
//                        is not virtual.
};

Also you can not assign a derived object to an instance of a base class, or slicing will occur.

std::vector<A> vec;
/* ... */
B b;
/* ... */
vec.push_back(b); // Slicing. Information only in B is lost.

Live example using virtual specifier

Live example without virtual specifier

like image 170
Felix Glas Avatar answered Sep 23 '22 21:09

Felix Glas