Question

I have a collection of SceneElements that I want to stream out. This is the aggregate class:

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

this is the base class:

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

and this is one of the derived classes:

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

but when i run this code:

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

it displays

<_SCN>SCENE ELEMENT<SCN_> 

rather than the actual element it was supposed to.

Was it helpful?

Solution

You need to store pointer to the base class in your vector.
While you think you addedderived class objects to the vector, each element in the vector has only enough space for a Base class object. So, what actually gets stored in the vector is just the Base object part. The derived class contents merely get sliced off.
This phenomenon is popularly known as Object slicing in C++.

Also, instead of storing raw pointers in the vector, You should consider using smart pointers.

OTHER TIPS

STL containers cannot be used polymorphically because its value semantics and requiring homogeneous storage size.

Each derived object can have different size than that of the base object.

In a container, it is hard to implement simple functions like:

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

if each "element" in between i and i+5 can have different size.

It therefore just uses the size of the static type, i.e. the base, for every items.

The way to get around this limitation is to use container of pointers. As all pointers are of the same size, regardless its type. and we can use pointers polymorphically.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top