Issues related to storing heterogeneous-sized objects in a vector

Discussion in 'C++' started by Ramon F Herrera, Jun 13, 2008.

  1. Newbie alert: I come from C programming, so I still have that frame of
    mind, but I am trying to "Think in C++". In C this problem would be
    solved using unions.

    Hello:

    Please consider the snippet below. I have some objects which are
    derived (subclassed?, subtyped?) from simpler ones, in increasing
    size. There is a linear hierarchy. I need to keep them all in some
    sort of linked list (perhaps std::vector). I could have several
    vectors, one for every different class, but I have an intuitive belief
    that C++ must be able to provide a means to save all the objects in
    the same vector.

    Issue #1: Notice the definition of the vector. Should I use the
    largest class (vector<pentagon>) to reserve space for the extreme
    case? Or, should I define a vector<triangle> instead since the others
    are inheritors of the triangle class?

    Maybe my approach is wrong to begin with?

    TIA,

    -RFH

    -------------------


    #include <vector>

    using namespace std;

    struct point
    {
    int x, y;
    };

    class triangle
    {
    public :
    point vertex1;
    point vertex2;
    point vertex3;
    };

    class square : public triangle
    {
    public :
    point vertex4;
    };


    class pentagon : public square
    {
    public :
    point vertex5;
    };


    int main()
    {
    vector<triangle> piggybank;
    triangle *love_affair = new triangle;
    square *boxing_ring = new square;
    pentagon *military = new pentagon;

    military->vertex5.x = 123;
    military->vertex5.y = 456;

    piggybank.push_back(*military);
    piggybank.push_back(*boxing_ring);
    piggybank.push_back(*love_affair);

    return 0;
    }
    Ramon F Herrera, Jun 13, 2008
    #1
    1. Advertising

  2. On Jun 12, 10:59 pm, Ramon F Herrera <> wrote:

    > Issue #1: Notice the definition of the vector. Should I use the
    > largest class (vector<pentagon>) to reserve space for the extreme
    > case? Or, should I define a vector<triangle> instead since the others
    > are inheritors of the triangle class?
    >



    Perhaps there is a way to specify all possible classes that will be
    welcome in the vector? This would be my guessed syntax:

    vector<triangle|square|pentagon> universal_container;

    Could this be a job for templates (which I barely understand)?

    -RFH
    Ramon F Herrera, Jun 13, 2008
    #2
    1. Advertising

  3. Ramon F Herrera

    Kai-Uwe Bux Guest

    Ramon F Herrera wrote:

    >
    > Newbie alert: I come from C programming, so I still have that frame of
    > mind, but I am trying to "Think in C++". In C this problem would be
    > solved using unions.
    >
    > Hello:
    >
    > Please consider the snippet below. I have some objects which are
    > derived (subclassed?, subtyped?) from simpler ones, in increasing
    > size. There is a linear hierarchy. I need to keep them all in some
    > sort of linked list (perhaps std::vector). I could have several
    > vectors, one for every different class, but I have an intuitive belief
    > that C++ must be able to provide a means to save all the objects in
    > the same vector.
    >
    > Issue #1: Notice the definition of the vector. Should I use the
    > largest class (vector<pentagon>) to reserve space for the extreme
    > case? Or, should I define a vector<triangle> instead since the others
    > are inheritors of the triangle class?
    >
    > Maybe my approach is wrong to begin with?


    Yes.


    > TIA,
    >
    > -RFH
    >
    > -------------------
    >
    >
    > #include <vector>
    >
    > using namespace std;
    >
    > struct point
    > {
    > int x, y;
    > };
    >
    > class triangle
    > {
    > public :
    > point vertex1;
    > point vertex2;
    > point vertex3;
    > };
    >
    > class square : public triangle


    This is not good. A square is not a triangle. The line above means that you
    can pass a square to each function that takes a triangle as an argument.
    But that will generally not make any sense.

    > {
    > public :
    > point vertex4;
    > };
    >
    >
    > class pentagon : public square
    > {
    > public :
    > point vertex5;
    > };
    >
    >
    > int main()
    > {
    > vector<triangle> piggybank;
    > triangle *love_affair = new triangle;
    > square *boxing_ring = new square;
    > pentagon *military = new pentagon;
    >
    > military->vertex5.x = 123;
    > military->vertex5.y = 456;
    >
    > piggybank.push_back(*military);
    > piggybank.push_back(*boxing_ring);
    > piggybank.push_back(*love_affair);


    Google for "slicing". All you do is copy the triangle subobjects into the
    vector.

    If you need a vector whose entries are polymorphic, you should consider

    vector< BaseClass * >

    or (usually better)

    vector< some_smart_pointer< BaseClass > >

    where the smart pointer would have the right semantics (e.g., deep copy if
    you want value semantics mimicking the behavior of containers most
    closely).

    > return 0;
    > }



    A more fundamental question is about the semantics of your objects. Are
    objects of type triangle supposed to be values (i.e., different objects can
    be the same triangle) or are they supposed to be entities (i.e., different
    objects will always be different also their member variables might have
    identical values). Containers work better with values, OOP in C++ works
    better with entities. Pointers interface between values and entities (since
    the address of an entity object is a value).


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Jun 13, 2008
    #3
  4. Ramon F Herrera

    Salt_Peter Guest

    On Jun 12, 10:59 pm, Ramon F Herrera <> wrote:
    > Newbie alert: I come from C programming, so I still have that frame of
    > mind, but I am trying to "Think in C++". In C this problem would be
    > solved using unions.
    >
    > Hello:
    >
    > Please consider the snippet below. I have some objects which are
    > derived (subclassed?, subtyped?) from simpler ones, in increasing
    > size. There is a linear hierarchy. I need to keep them all in some
    > sort of linked list (perhaps std::vector). I could have several
    > vectors, one for every different class, but I have an intuitive belief
    > that C++ must be able to provide a means to save all the objects in
    > the same vector.


    You certainly can, assuming you design a hierarchy that supports a
    base type.
    Think 'Shapes'

    >
    > Issue #1: Notice the definition of the vector. Should I use the
    > largest class (vector<pentagon>) to reserve space for the extreme
    > case? Or, should I define a vector<triangle> instead since the others
    > are inheritors of the triangle class?
    >
    > Maybe my approach is wrong to begin with?
    >
    > TIA,
    >
    > -RFH


    Consider the following, lets forget the coordinate system for now

    #include <iostream>
    #include <vector>

    class Shape { };
    class Triangle : public Shape { };
    class Rectangle : public Shape { };
    class Circle : public Shape { };

    int main()
    {
    std::vector< Shape* > shapes;

    Triangle tri;
    Rectangle rect;
    Circle circ;

    shapes.push_back(&tri);
    shapes.push_back(&rect);
    shapes.push_back(&circ);

    std::cout << "vector shapes has ";
    std::cout << shapes.size() << " elements\n";
    }


    >
    > -------------------
    >
    > #include <vector>
    >
    > using namespace std;
    >
    > struct point
    > {
    > int x, y;
    >
    > };
    >
    > class triangle
    > {
    > public :
    > point vertex1;
    > point vertex2;
    > point vertex3;
    >
    > };
    >
    > class square : public triangle
    > {
    > public :
    > point vertex4;
    >
    > };
    >
    > class pentagon : public square
    > {
    > public :
    > point vertex5;
    >
    > };
    >
    > int main()
    > {
    > vector<triangle> piggybank;
    > triangle *love_affair = new triangle;
    > square *boxing_ring = new square;
    > pentagon *military = new pentagon;
    >
    > military->vertex5.x = 123;
    > military->vertex5.y = 456;
    >
    > piggybank.push_back(*military);
    > piggybank.push_back(*boxing_ring);
    > piggybank.push_back(*love_affair);
    >
    > return 0;
    >
    > }


    I'ld suggest choosing a smart_pointer instead of new.
    You would end up with something like the following (using
    boost::shared_ptr in this case)

    #include <iostream>
    #include <vector>
    #include "boost/smart_ptr.hpp"

    class Shape { };

    class Triangle : public Shape
    {
    public:
    ~Triangle(){ std::cout << "~Triangle\n"; }
    };

    class Rectangle : public Shape
    {
    public:
    ~Rectangle(){ std::cout << "~Rectangle\n"; }
    };

    class Circle : public Shape
    {
    public:
    ~Circle(){ std::cout << "~Circle\n"; }
    };

    int main()
    {
    std::vector< boost::shared_ptr<Shape> > shapes;

    // Triangle tri;
    // Rectangle rect;
    // Circle circ;

    shapes.push_back(boost::shared_ptr<Shape>(new Triangle));
    shapes.push_back(boost::shared_ptr<Shape>(new Rectangle));
    shapes.push_back(boost::shared_ptr<Shape>(new Circle));

    std::cout << "vector shapes has ";
    std::cout << shapes.size() << " elements\n";
    }

    /*
    vector shapes has 3 elements
    ~Triangle
    ~Rectangle
    ~Circle
    */

    The above uses default constructors only, if parametized ctors are
    supplied, the concept remains the same.
    Salt_Peter, Jun 13, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. thechaosengine

    Oddly sized sized password textbox

    thechaosengine, Sep 15, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    569
    David Hearn
    Sep 15, 2005
  2. jjleto
    Replies:
    2
    Views:
    376
    jjleto
    Nov 12, 2004
  3. Replies:
    8
    Views:
    1,890
    Csaba
    Feb 18, 2006
  4. Replies:
    2
    Views:
    387
    Juha Nieminen
    Sep 8, 2008
  5. Bill Ward

    Heterogeneous objects and a GridView

    Bill Ward, Jan 23, 2007, in forum: ASP .Net Web Controls
    Replies:
    0
    Views:
    157
    Bill Ward
    Jan 23, 2007
Loading...

Share This Page