在向量C ++中从超类调用子类方法

时间:2014-07-19 19:19:06

标签: c++ pointers inheritance vector superclass

我试图在向量中添加一些子类元素,遍历它们调用重写方法并希望它尽可能调用重写方法。但是我发现它似乎只是调用超类方法。

我学习了Java并且不确定它为什么在C ++中这样做。我尝试使用超类的指针向量重写代码,并将子类的指针强制转换为超类。通过指针访问它然后工作。

理想情况下,我不希望必须将一个指针列表放入向量中,因为那时我必须手动删除每一个(我相信?)以阻止内存泄漏,因为我将使用new创建对象,因此它们会持续超过方法调用将它们添加到向量中。

有没有更好的方法可以做到这一点,还是我坚持使用指针并在不需要父类时在创建的对象上调用delete?优选地,向量将是类X的列表而不是类X的指针列表

我的结构是:

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() }

代码来演示我理想的做什么,但仅通过调用超类方法来显示它的缺失:

#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
    }

}

5 个答案:

答案 0 :(得分:4)

要获得所需的多态行为,需要将virtual说明符添加到要在派生类中覆盖的基类中的函数。

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

您还应养成在派生类中重写函数添加override说明符的习惯,以便编译器可以帮助您解决这些问题。

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

此外,您无法将派生对象分配给基类的实例,或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

答案 1 :(得分:0)

您应该将方法声明为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"); }
};

答案 2 :(得分:0)

该方法应为virtual 在java中,默认情况下方法是虚拟的。

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
};

答案 3 :(得分:0)

我认为您缺少的是方法声明中的virtual关键字。如果要在父类中调用方法时获取子类方法,则必须声明方法virtual

答案 4 :(得分:0)

如果你不使用指针,你会得到对象切片&#39;将对象复制到向量时。这会将对象减少为向量模板参数中声明的基类型。所以没有子类,所以没有子类方法可以调用,即使该方法是虚拟的。