views:

307

answers:

4

Hey,

I have 2 classes:

class Base
{
public:
     virtual int Foo(int n);
         virtual void Goo() = 0;
     virtual ~Base() ;
};


class Derived : public Base
{
public:
    int Add4Bytes;

        void Goo();
    int  Foo(int n);    
};

int Test(Base* b)
{
    for (int i=0;i<5;++i)
    {
        b->Foo(i);
        ++b;
    }
    return 0;
}

void Test2(Base arr[])
{
    for (int i=0;i<5;++i)
    {
        arr[i].Foo(i);
    }
}

void main
{

      Base* b = new Derived[5];
      Test(b);
}

So, when i'm calling Test, after the second loop there a memory viloation exception.

I have 2 questions:

  1. What's the difference between the function argument in Test and Test2 ? (Test2 doesn't compile after i turned Base into pure abstract class).

and the more important question

  1. How can i prevent that exception, and how can i pass an array of derived class to a function that suppose to get a base class array. (i can't tell in compile time which derived class i'm gonna pass the function)

p.s - please don't tell me to read Meyers book, that's the exact reason why i'm asking this question. :)

Thanks

+4  A: 

There's no difference between the parameter types, array parameters are adjusted to pointers in function declarations.

While you can convert a pointer to Derived to a pointer to Base, you can't treat an array of Derived as an array of Base, they are not related types. This is because in an array of Derived, the Base class is a sub-object of Derived and not part of an array of Base. When you perform pointer arithmetic as though it were part of an array of Base you are getting undefined behaviour, you are likely to construct a Base pointer that doesn't point exactly at the start of a Base object.

Charles Bailey
+1  A: 
Nikolai N Fetissov
+3  A: 

Arrays don't deal well with polymorphic types as contents due to object slicing. An array element has a fixed size, and if your derived objects have a larger size than the base then the array of base objects can't actually hold the derived objects.

Even though the function parameter might be decaying into a pointer, the pointer arithmetic done on that pointer will be based on the element size of the array type.

To deal with arrays of polymorphic types, you'll need to add another level of indirection and deal with arrays (or some other container) of pointers to the objects.

Test2 doesn't compile after i turned Base into pure abstract class

You can't have arrays of abstract types because you can't have instances of abstract types (only pointers or references to them).

Michael Burr
A: 

You can find additional information about arrays of base and derived classes in C++ FAQ Lite question 21.4: Is an array of Derived a kind-of array of Base?

Liz Albin