I have 2 classes:
class Base
{
public:
virtual int Foo(int n);
virtual void Goo() = 0;
virtual ~Base() ;
};
class Derived : public Base
{
public:
int开发者_C百科 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:
- 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
- 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
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.
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).
Your Test
function steps through array of Base
objects, i.e. the stride is sizeof( Base )
, while it needs to be sizeof( Derived )
. You probably want to declare it as:
int Test( const std::vector<Base*>& );
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
?
精彩评论