C ++多态和切片

时间:2010-04-04 17:42:22

标签: c++ polymorphism object-slicing

以下代码打印出来

Derived
Base
Base

但我需要将每个Derived对象放入User :: items,调用自己的print函数,而不是基类。我可以在不使用指针的情况下实现吗?如果不可能,我应该如何编写逐个删除User :: items并释放内存的函数,以便不会有任何内存泄漏?

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Base{
public:
  virtual void print(){ cout << "Base" << endl;}
};

class Derived: public Base{
public:
  void print(){ cout << "Derived" << endl;}
};

class User{
public:
  vector<Base> items;
  void add_item( Base& item ){
    item.print();
    items.push_back( item );
    items.back().print();
  }
};

void fill_items( User& u ){
  Derived d;
  u.add_item( d );
}

int main(){
  User u;
  fill_items( u );
  u.items[0].print();
}

3 个答案:

答案 0 :(得分:5)

您需要使用指针,并且需要为基类提供虚拟析构函数。析构函数不必执行任何操作,但必须存在。您的添加功能如下所示:

void add_item( Base * item ){
    item->print();
    items.push_back( item );
}

其中的项目为vector<Base *>。销毁项目(假设是虚拟析构函数):

for( int i = 0; i < items.size(); i++ ) {
    delete items[i];
}
items.clear();

答案 1 :(得分:1)

你需要一个基于虚拟析构函数来确保在Derived类型的指针上调用delete时,类型Base的对象被正确销毁。

class Base{
public:
  virtual void print(){ cout << "Base" << endl;}

  virtual ~Base( ) { }  // virtual destructor
};

然后你可以使用Boosts ptr_vector存储指向你的对象的指针,当容器被销毁时会被删除。

答案 2 :(得分:0)

刚才解释:

为了理解发生了什么,您可以尝试定义类Base抽象(例如,定义任何纯虚拟方法)。在这种情况下,我希望你会看到编译器错误。 通过这种方式,您将识别向量实际执行的操作:当您执行push_back(派生)时,它会通过复制构造创建类Base的新实例。 这就是你想要使用指针的原因。然后,vector可以使用最初创建的Derived类型的对象,而不是自己的Base类型副本。