为什么我不能在基类型std:vector中存储派生类?

时间:2015-03-19 06:09:38

标签: c++

我知道这可能是一个非常简单的问题,但它确实让我困惑了几天。我尝试将派生类存储在存储基类类型的标准std:vector中。 如果我使基(父)类成为纯虚拟类。我无法在向量中存储派生类。 如果我实现了基(父)类的getName()方法。我可以成功建立。但是在对矢量进行迭代时。它失去了多态性......

#include "stdafx.h"
#include <string>
#include <iostream>
#include <vector>
using namespace std;

class father{
public:
    //virtual string getName() = 0; //If uncomment here. push_back(c1) will induce build error.
    virtual string getName(){ return "father";}
};

class child1 : public father{
public:
    virtual string getName(){
        return "child1";
    }
};

class child2 : public father{
public:
    virtual string getName(){
        return "child2";
    }
};

class child3 : public father{
public:
    virtual string getName(){
        return "child3";
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    child1 c1;
    child2 c2;
    child3 c3;

    cout<< "c1  " << sizeof(c1) << endl;
    cout<< "c2  " << sizeof(c2) << endl;
    cout<< "c3  " << sizeof(c3) << endl;

    vector<father> v;
    v.push_back(c1); //build error if Father is pure virtual class
    v.push_back(c2); //build error
    v.push_back(c3); //build error

    for(std::vector<father>::iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << "I'm " << it->getName() << endl; //lose polymorphism
    }
    return 0;
}

总结两个问题: 1.为什么将base(father)类定义为纯虚拟类。我无法在向量中存储派生类? 2.为什么当我再次从矢量中获得课程时。它失去了多态性?

提前感谢您的帮助。真的很感激!

2 个答案:

答案 0 :(得分:1)

这是因为在C ++中,向量存储father,它本身就是一个对象。在Java等其他语言中,您将隐式存储对原始对象(子项)的引用。

当构造存储在向量内的father对象时,切片复制的对象。

如果你想在C ++中使用类似于Java的东西,请使用:

std::vector<std::shared_ptr<father>> v;

答案 1 :(得分:0)

  
      
  1. 为什么将base(father)类定义为纯虚拟类。我不能在vector中存储派生类?
  2.   

您声明了father的向量,如果father是一个abstrcat类,则无法实例化它。即使您将child的实例放入其中,也会将其复制(切片)为father

  
      
  1. 为什么当我再次从矢量中获得课程时。它失去了多态性?
  2.   

如果要保持多态性,则必须通过指针或引用访问对象。在您的情况下,最好使用智能指针而不是原始指针,例如:

vector<shared_ptr<father>> v;
v.push_back(new child1);
v.push_back(new child2);
v.push_back(new child3);

for (auto it = v.begin(); it != v.end(); ++it)
{
    cout << "I'm " << (*it)->getName() << endl;
}