std::vector holding different class types sharing a same base class 
Author Message
 std::vector holding different class types sharing a same base class

Hi,

I'm about to add something to a library of mine, and although tests will
compile OK, I'd like to make sure it won't{*filter*}me up in the long run.

Let's say I have two classes derived from a virtual base class as such:

class C_TheBaseClass {
    protected:
    C_TheBaseClass (void); // Make the class uninstanciable
    public:
    int m_SomeMember;
    enum {
        Type_One,
        Type_Two
        } m_Type;
    };

class C_DerivedClassOne : public C_TheBaseClass {
    public:
    C_DerivedClassOne (unsigned char Value) {
        m_Type = Type_One;
        m_SmallMember = Value;
        };
    unsigned char m_SmallMember;
    };

class C_DerivedClassTwo : public C_TheBaseClass {

    public:
    C_DerivedClassTwo (unsigned long Value) {
        m_Type = Type_Two;
        m_LargeMember = Value;
        };
    unsigned long m_LargeMember;
    };

I'd like a vector to contain instances of DerivedClassOne's or
DerivedClassTwo's. Since they share the same base class and therefore
share the m_Type member, by making my vector a vector of
C_TheBaseClass'es I could, as I iterate through the vector, switch on
m_Type and then use m_SmallMember or m_LargeMember, depending on the
type of class contained in the vector. Here's an example:

C_DerivedClassOne Moo1 (10);
C_DerivedClassTwo Moo2 (2000000);
C_DerivedClassOne Moo3 (30);
std::vector <C_TheBaseClass> m_Vector; // Note that it will contain
instances, not pointers
m_Vector.push_back ((C_TheBaseClass)Moo1); // Added a C_DerivedClassOne
m_Vector.push_back ((C_TheBaseClass)Moo2); // Added a C_DerivedClassTwo
m_Vector.push_back ((C_TheBaseClass)Moo3); // Added a C_DerivedClassOne
for (std::vector <C_TheBaseClass>::iterator ThisVector = m_Vector.begin
(); ThisVector < m_Vector.end (); ThisVector ++)
    switch (ThisVector->m_Type) {
        case C_Vector::Type_One:
            C_DerivedClassOne *One = (C_DerivedClassOne *)ThisVector;
            One->m_SmallMember ++;
            break;
        case C_Vector::Type_Two:
            C_DerivedClassTwo *Two = (C_DerivedClassTwo *)ThisVector;
            Two->m_LargeMember ++;
            break;
        };

That sounds good to me (although I'm not 100% sure of the syntax as I
don't have a C++ compiler with me right now), and my test at home
compiles OK... But how would the std::vector know how much space to
allocate for each element it will contain? My C_DerivedClassOne and
C_DerivedClassTwo are of different sizes..!

I realize most people won't have read up to this point, but if someone
does, I'ld really appreciate some enlightenment!

Thanks
    Alex



Mon, 07 Jul 2003 01:38:11 GMT  
 std::vector holding different class types sharing a same base class
-- below...

--
Reginald Blue                   | Opinions expressed here do not
Natural Language Understanding  | necessarily represent those of
Unisys Corporation              | my employer.
--------------------------------+-------------------------------

NL technology,speech application| My email address is wrong, you
development training, see:      | need to remove the obvious.
http://www.speechdepot.com/     +-------------------------------


Quote:
> Hi,

<sample code deleted>

Quote:

> That sounds good to me (although I'm not 100% sure of the syntax as I
> don't have a C++ compiler with me right now), and my test at home
> compiles OK... But how would the std::vector know how much space to
> allocate for each element it will contain? My C_DerivedClassOne and
> C_DerivedClassTwo are of different sizes..!

> I realize most people won't have read up to this point, but if someone
> does, I'ld really appreciate some enlightenment!

-- I did.  The answer is:  You can't do what you're trying to do.  When you
assign (push_back) the derived classes they get copy-constructed back into
base classes and lose all of the extra information, and the space allocated
by std::vector is exactly (and only) enough to handle the base class.

-- You must use pointers directly (or indirectly through smart pointers) to
get polymorphic behavior in the STL container classes.  (You can't even use
references because the STL container classes don't support that.) Sorry.



Mon, 07 Jul 2003 01:50:54 GMT  
 std::vector holding different class types sharing a same base class
Hi Reginald,

Yeah I didn't think about the actual instanciation of my C_TheBaseClass when I
add them to the vector. So I guess the proper way of doing this would be like
the following: (taking my original example):

C_DerivedClassOne *Moo1 = new C_DerivedClassOne (10);
C_DerivedClassTwo *Moo2 = new C_DerivedClassTwo (2000000);
C_DerivedClassOne *Moo3 = new C_DerivedClassOne (30);
std::vector <C_TheBaseClass *> m_Vector;
m_Vector.push_back ((C_TheBaseClass *)Moo1);
m_Vector.push_back ((C_TheBaseClass *)Moo2);
m_Vector.push_back ((C_TheBaseClass *)Moo3);
for (std::vector <C_TheBaseClass *>::iterator ThisVector = m_Vector.begin ();
ThisVector < m_Vector.end (); ThisVector ++)
    switch ((C_TheBaseClass *)(*ThisVector)->m_Type) {  // Not 100% sure about
the iterator cast here
        case C_Vector::Type_One:
            C_DerivedClassOne *One = (C_DerivedClassOne *)ThisVector;
            One->m_SmallMember ++;
            break;
        case C_Vector::Type_Two:
            C_DerivedClassTwo *Two = (C_DerivedClassTwo *)ThisVector;
            Two->m_LargeMember ++;
            break;
        };

As long as I make sure I iterate through my vector before it goes out of scope
/ gets destroyed and release its contents with delete, I think this would
work...

Thanks
    - Alex

Quote:

> -- I did.  The answer is:  You can't do what you're trying to do.  When you
> assign (push_back) the derived classes they get copy-constructed back into
> base classes and lose all of the extra information, and the space allocated
> by std::vector is exactly (and only) enough to handle the base class.

> -- You must use pointers directly (or indirectly through smart pointers) to
> get polymorphic behavior in the STL container classes.  (You can't even use
> references because the STL container classes don't support that.) Sorry.



Mon, 07 Jul 2003 02:35:14 GMT  
 std::vector holding different class types sharing a same base class
-- below...

--
Reginald Blue                   | Opinions expressed here do not
Natural Language Understanding  | necessarily represent those of
Unisys Corporation              | my employer.
--------------------------------+-------------------------------

NL technology,speech application| My email address is wrong, you
development training, see:      | need to remove the obvious.
http://www.speechdepot.com/     +-------------------------------


Quote:
> As long as I make sure I iterate through my vector before it goes out of
scope
> / gets destroyed and release its contents with delete, I think this would
> work...

-- Yes, it looks like it will work to me.  As for "remembering to delete",
this is why I suggested using some form of smart pointer to take care of
this for you.  FWIW, boost (http://boost.org ) has a reference counted smart
pointer template which could make your life easier in this regard.  Your
call if you want to use it.

-- Just to steer you away from possible trouble, do NOT think of using
std::auto_ptr.  It does not work correctly in container classes.



Mon, 07 Jul 2003 03:10:31 GMT  
 std::vector holding different class types sharing a same base class
Thanks a lot for your help!

    - Alex

Quote:

> -- Yes, it looks like it will work to me.  As for "remembering to delete",
> this is why I suggested using some form of smart pointer to take care of
> this for you.  FWIW, boost (http://boost.org ) has a reference counted smart
> pointer template which could make your life easier in this regard.  Your
> call if you want to use it.

> -- Just to steer you away from possible trouble, do NOT think of using
> std::auto_ptr.  It does not work correctly in container classes.



Mon, 07 Jul 2003 22:25:49 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. export classes using std namespace (ex std::vector) in a DLL

2. address of base class and derived class different

3. std::vector passed to DLL class never arrives???

4. std::vector class

5. VC++ 5.0 std::vector error: pointer to nested class

6. Protected member in a base class of a base class

7. std::vector<user-defined class>

8. using std::string and vector in DLL exported class

9. class class-name: base-class : interface

10. Trying to add a class with no base class in Class Wizard

11. problem using std::string as base class

12. How to share MFC class in memory in DLL that is called by different application

 

 
Powered by phpBB® Forum Software