虚函数不执行派生类版本

时间:2013-01-21 03:40:03

标签: c++ inheritance object-slicing

我有一个我希望流出的SceneElements集合。这是聚合类:

class scene{
public:
    vector<sceneElement> elements;
    void addElement(sceneElement);
    void toStream(std::ostream &);
    void fromStream(std::istream &);
};

void scene::addElement(sceneElement e){
    elements.insert(elements.end(), e);
}

void scene::toStream(std::ostream &strm){
    strm << SCENE_PRE;
    int i;
    for(i=0; i<elements.size(); i++){
        elements[i].toStream(strm);
    }
    strm << SCENE_POST;
}

这是基类:

class sceneElement{
public:
    virtual void toStream(std::ostream &);
    virtual void fromStream(std::istream &);
};

void sceneElement::toStream(std::ostream &str){
    str << "SCENE ELEMENT";
}

void sceneElement::fromStream(std::istream &){
    std::cerr << "this is not supposed to be called";
}

,这是派生类之一:

class camera : public sceneElement{
public:
    P3d location;
    P3d direction;
    double fov;
    int toString(char**);
    virtual void toStream(std::ostream &);
    virtual void fromStream(std::istream &);
};

void camera::toStream(std::ostream &strm){
    strm << CAMERA_PRE << TAG_LOCATION;
    location.toStream(strm);
    strm << TAG_DIRECTION;
    direction.toStream(strm);
    strm << TAG_FOV << fov << CAMERA_POST;
}

但是当我运行此代码时:

scene sc;
sc.addElement(s);
sc.toStream(cout);

显示

<_SCN>SCENE ELEMENT<SCN_> 

而不是它应该的实际元素。

2 个答案:

答案 0 :(得分:2)

您需要将指针存储到向量中的基类 虽然您认为向向量添加了类对象,但向量中的每个元素只有足够的空间用于Base类对象。因此,实际存储在向量中的只是Base对象部分。派生类内容仅仅 切掉 这种现象在C ++中通常被称为 Object slicing

此外,不应将原始指针存储在向量中,而应考虑使用智能指针。

答案 1 :(得分:1)

STL容器不能以多态方式使用,因为它的值语义并且需要同类存储大小。

每个派生对象的大小可以与基础对象的大小不同。

在容器中,很难实现简单的功能,如:

vector<Element> v;
..
int i;
Element e = v [i+5]; 

如果i和i + 5之间的每个“元素”可以具有不同的大小。

因此,它只使用每个项目的静态类型的大小,即基数。

解决此限制的方法是使用指针容器。因为所有指针都具有相同的大小,无论其类型如何。我们可以多态地使用指针。