简体   繁体   中英

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
    }

}

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

You should declare the methods as virtual in order to be able to override them in a subclass. Also it's good practice to make the destructor virtual.

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

class B: public A {
public:
   // using virtual is not really necessary here, but it's good for clarity.
   virtual void talk() { printf("B\n"); }
};

The method should be virtual .
In java methods are virtual by default.

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

class B: public A {
  public:
      virtual void talk() override { printf("B\n"); } //override key word is in C++  0x and above
};

I think what you are missing is the virtual keyword in your method declaration. If you want to get to a subclass method when invoking methods in a parent class, the methods have to be declared virtual .

If you don't use a pointer you will get 'object slicing' when you copy the object into the vector. This reduces the object to the base type declared in the vector template argument. So there is no subclass, so no subclass method to call, even if the method is virtual.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM