Freddie
Freddie

Reputation: 1707

C++ allocating space for objects using inheritance

I've got a question about how a C++ compiler knows how much space it needs to allocate for an object when using inheritance.

Imagine the following classes, for an adult and a child which extend a Person class, but where a child has a short book with them.

class Person
{
    
};

class Adult : public Person
{
    //No book
};

class Child : public Person
{
   char book[1000]; //Stores the book
};

Now if you create an array of Person objects, and add objects to them:

Adult adult1;
Child child1;

Person people[2];
people[0] = child1;
people[1] = adult1;

My question is: How does the compiler know how much space it needs to ensure the array is a contiguous memory block, if it doesn't know whether the array will be filled with Adult or Child (which are much different sizes) objects?

I hope this makes enough sense to answer...

Upvotes: 9

Views: 1785

Answers (6)

doron
doron

Reputation: 28872

In a nutshell, there is no such thing as a virtual constructor in C++, when creating an object you have to know exactly what you are creating. Once the object is created, you can use polymorphism derived class specific behaviour from a base class. In your case when creating a Person object only a Person object is created. If Person has a pure virtual method, the compiler will refuse to create it.

In the event that you are unsure whether to create a Parent or a Child Object you can use a polymorphic Abstract PersonFactory although when creating the factory, for the same reason, you will have to know exactly what type of concrete object you are creating.

Upvotes: 0

Cameron
Cameron

Reputation: 98746

Since your array is of type Person, the compiler doesn't know to declare enough space for children and adults. It just declares enough for two people.

Each time you put in a child or adult, the object will get "sliced" off, keeping only the Person part of the object.

The standard way to get around this is to declare an array of People pointers (which are all of constant size regardless of what they point to, since they're really just memory addresses), which can point to objects of any of your classes.

Upvotes: 3

El Marcel
El Marcel

Reputation: 1785

This is an excellent question.

The answer is that it doesn't. It allocated enough space only for the fields of the People class. When you copy a child into it, only the people parts (hehe) get copied. See What is object slicing?.

If you really want want to do this operation, you should probably be using pointers.

Upvotes: 1

Reinderien
Reinderien

Reputation: 15211

The assignment you've shown doesn't make too much sense. Yes, the array as you show it will be contiguous, but it won't have space for any of the derived class members, and when you perform that assignment those data will be dropped (if the compiler even permits it, which I'm not sure it will).

Upvotes: 0

Yochai Timmer
Yochai Timmer

Reputation: 49221

If you're not creating an array of pointers, Person people[2]; will assign enough space for 2 objects of type Person.

When you'll assign a Child to the Person only the Person traits of Child will be copied.

Upvotes: 1

James McNellis
James McNellis

Reputation: 355009

How does the compiler know how much space it needs to ensure the array is a contiguous memory block, if it doesn't know whether the array will be filled with Adult or Child

The people array cannot contain Adult or Child objects: it can only contain Person objects.

When you perform the assignment people[0] = child1;, what actually happens is the Person parts of the child1 object are assigned to people[0]. All of the Child parts are effectively ignored.

This behavior, where only the base class parts of an object are copied, is called "slicing."

To get polymorphic behavior in C++, you must use either pointers are references. Since it is impossible to have an array of references, you would need to use an array of pointers.

Upvotes: 14

Related Questions