C ++ выделяет пространство для объектов, используя наследование - PullRequest
8 голосов
/ 30 июля 2011

У меня есть вопрос о том, как компилятор C ++ знает, сколько места ему нужно выделить для объекта при использовании наследования.

Представьте себе следующие классы для взрослого и ребенка, которые расширяют класс Person, но где у ребенка есть небольшая книга с ними.

class Person
{

};

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

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

Теперь, если вы создаете массив объектов Person и добавляете к ним объекты:

Adult adult1;
Child child1;

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

Мой вопрос: Как компилятор узнает, сколько места ему нужно, чтобы массив был смежным блоком памяти, если он не знает, будет ли массив заполнен объектами Adult или Child (которые очень разных размеров)?

Надеюсь, в этом есть смысл ответить ...

Спасибо

Ответы [ 6 ]

12 голосов
/ 30 июля 2011

Как компилятор знает, сколько места ему нужно, чтобы массив был непрерывным блоком памяти, если он не знает, будет ли массив заполнен Adult или Child

Массив people не может содержать Adult или Child объектов: он может содержать только Person объектов.

Когда вы выполняете присваивание people[0] = child1;, на самом деле происходитPerson части объекта child1 присвоены people[0].Все части Child фактически игнорируются.

Такое поведение, при котором копируются только части базового класса объекта, называется "нарезкой".

Чтобы получить полиморфное поведение в C ++Вы должны использовать любые указатели ссылки.Поскольку невозможно получить массив ссылок, вам нужно использовать массив указателей.

3 голосов
/ 30 июля 2011

Поскольку ваш массив имеет тип Person, компилятор не знает, как объявить достаточно места для детей и взрослых. Это просто объявляет достаточно для двух человек.

Каждый раз, когда вы добавляете ребенка или взрослого, объект будет «обрезан», оставляя только личную часть объекта.

Стандартный способ обойти это состоит в том, чтобы объявить массив указателей People (которые имеют постоянный размер независимо от того, на что они указывают, поскольку они на самом деле просто адреса памяти), которые могут указывать на объекты любого из ваши занятия.

1 голос
/ 30 июля 2011

Это отличный вопрос.

Ответ в том, что это не так. Выделено достаточно места только для полей класса People. Когда вы копируете в него ребенка, копируются только части людей (хе-хе). См. Что такое нарезка объектов? .

Если вы действительно хотите выполнить эту операцию, возможно, вам следует использовать указатели.

1 голос
/ 30 июля 2011

Если вы не создаете массив указателей, Person people[2]; назначит достаточно места для 2 объектов типа Person .

Когда вы назначите Child для Персона будет скопирована только Персона черт Ребенок .

0 голосов
/ 30 июля 2011

В двух словах, в C ++ нет такого понятия, как виртуальный конструктор, при создании объекта вы должны точно знать, что вы создаете.Как только объект создан, вы можете использовать поведение базового класса, полученное из полиморфизма.В вашем случае при создании объекта Person создается только объект Person.Если Person имеет чисто виртуальный метод, компилятор откажется его создавать.

В случае, если вы не уверены, создавать ли объект Parent или Child, вы можете использовать полиморфный АннотацияPersonFactory хотя при создании фабрики по той же причине вам необходимо точно знать, какой тип конкретного объекта вы создаете.

0 голосов
/ 30 июля 2011

Задание, которое вы показали, не имеет особого смысла. Да, массив, как вы показываете, будет смежным, но в нем не будет места ни для одного из производных членов класса, и когда вы выполните это назначение, эти данные будут удалены (если компилятор даже разрешит это, что я не уверен, что так и будет).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...