Click here to Skip to main content
15,892,537 members

Response to: dynamic array of interfaces

Latest Revision
If you are using polymorphism then you have to use a pointer or reference, you can not achieve polymorphism with values.
In this case:
C++
MyInterface *a;
a = new MyClass[n];
for (int i=0; i<n; i++) {
    a[i].myFunction ();
}

Your MyInterface *a "array" stores the the class instances themselves as values. Your assignment a = new MyClass[n]; compiles (compiles - not works) just because you explited a relatively dangerous trait of C, that is array identifiers of type T and pointers to type T are exchangeable and auto-casted in most situations (except for a few cases with templates and function parameters).

Both solution A and B are correct though. Your A case takes much more memory because you allocated a lot of small chunks instead of one big chunk and that can lead to memory fragmentation if you regularly free/allocate chunks but in your case the extra wasted space probably comes from memory usage of your allocator that uses some extra memory per allocated block to keep track of allocated/free space in your heap.

However if you need to provide MyInterface **a then you can mix solution A and B as an optimization, you allocate both a MyInterface **a like in solution A and a MyClass *b like in solution B and then later you can fill in the a interface pointers to point to the items of the b array.

EDIT: Forgot to mention something that is much more like an answer to your problem:
C++
class Base
{
public:
    Base(int base_data=0)
        : m_BaseData(base_data)
    {
    }
private:
    int m_BaseData;
};

class Derived : public Base
{
public:
    Derived(int derived_data=0)
        : m_DerivedData(derived_data)
    {
    }
private:
    int m_DerivedData;
};

void test()
{
    // EXAMPLE #1
    const int ARRAY_SIZE = 5;
    Base* base_array = new Base[ARRAY_SIZE];
    Derived* derived_array = new Derived[ARRAY_SIZE];
    printf("base_array member_size: %d\n", (int)((char*)&base_array[1]-(char*)&base_array[0]));
    // note: base_array member_size is 4 on my machine
    printf("derived_array member_size: %d\n", (int)((char*)&derived_array[1]-(char*)&derived_array[0]));
    // note derived_array member_size is 8 on my machine

    base_array = new Derived[ARRAY_SIZE];
    // note that the first (index 0) member pointed by base_array will be accessed perfectly
    // because the assignment performed a static cast (!!!) and adjusted the pointer (by offsetting
    // it if needed). However if you perform an indexing on a (Base*) type then you will be
    // accessing a memory area that is 4 bytes (base_array member_size) past the current value
    // of the pointer and this gives a wrong result since you allocated a Derived array whose
    // members are 8 bytes large. For this simple reason you MUST always assign a dynamically
    // allocated C++ array to exactly same type of pointer as the type of the members in the array!!!

    // EXAMPLE #2
    Derived derived;
    // This is another common mistake related to inheritance and storing instances by value:
    // Copying only the base of a larger object that is an instance of a class derived from the base class.
    // This is perfectly valid in many cases but sometimes it causes a bug, sometimes you store
    // data in the base part of the derived class that is not valid without the derived parts of
    // the object. To disable copying just the base part of an instance put the base class copy
    // constructor to protected.
    Base base(derived);
    // OR
    Base base2 = derived;
}
Posted 21-Sep-12 4:08am by pasztorpisti.
Tags: