1

我有一组要流出的 SceneElement。这是聚合类:

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_> 

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

4

2 回答 2

2

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

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

于 2013-01-21T03:45:08.270 回答
1

STL 容器不能多态使用,因为它的值语义和需要同质的存储大小。

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

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

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

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

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

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

于 2013-01-21T04:43:55.397 回答