порядок уничтожения с использованием виртуального - PullRequest
9 голосов
/ 18 августа 2010

Может кто-нибудь помочь, пожалуйста, каков порядок уничтожения, когда я использую виртуальные функции. Начинается ли он с базового класса, а затем производного класса?

Ответы [ 8 ]

10 голосов
/ 18 августа 2010

Поскольку я не вижу, как виртуальная функция изменяет порядок уничтожения каких-либо объектов, я предполагаю, что вы имеете в виду порядок уничтожения для базовых классов и элементов данных в виртуальном наследовании сценарий.

Подобъекты построены

  1. базовые классы построены от большинства базовых к большинствупроизводные ;
  2. несколько базовых классов создаются в порядке их объявления в качестве базовых классов ;
  3. виртуальных базовых классов построены раньше всех остальных , между собой придерживаясь вышеуказанных двух правил;
  4. члены данных создаются до того, как тело конструктора окружающего объекта будет выполнено , в порядке их объявления.

Уничтожение - это просто противоположность конструкция , поэтому вам нужно запомнить только вышеперечисленное.

Тем не менее, вышеприведенные четыре правила находятся в таком порядке, потому что это имеет смысл, и если вы понимаете, почему этот порядок имеет смысл, вам даже не придется запоминать эти четыре правила, но вы можете вывести их из вашего понимания (как я только что сделал).Итак, давайте рассмотрим этот порядок:

  • Возможно, вы захотите использовать любой сервис, предоставляемый базовым классом из конструктора производного класса.Конечно, вы не можете использовать (базовый) объект класса до его фактического создания.Следовательно, когда создается производный класс, базовый класс должен быть уже создан.(Между прочим, это также объясняет, почему диспетчеризация виртуальных функций не полностью работает из конструкторов: когда создается подобъект, только подобъекты базовых классов уже созданы; подобъекты производных классов еще не созданыПоэтому вызов виртуальной функции не должен отправляться производному классу. Как всегда, деструкторы одинаковы, только в обратном направлении.)
  • Поскольку несколько базовых классов являются одинаковыми братьями и сестрами, необходимо было выбрать некоторый порядокпроизвольно.В конечном счете, порядок объявления является наиболее простым в использовании.Члены данных, которые также являются равными братьями и сестрами, следуют одному и тому же (более или менее произвольному) правилу порядка объявления.
  • Виртуальные базовые классы - странные звери.Поскольку в виртуальном базовом классе всегда будет только один подобъект, существует специальное правило, которое гласит, что его всегда нужно создавать сначала прямо из конструктора самого производного класса.(Вот почему виртуальные базовые классы лучше всего работают как абстрактные базовые классы без данных и только с конструкторами по умолчанию.)
5 голосов
/ 18 августа 2010

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

Тогда уничтожение выполняется в порядке, обратном порядку построения.

В общем случае это будет:

A) Начать с самого производного класса.
B) Повторить следующее рекурсивно.

1) Выполнить код деструктора.
2) Выполнить деструктор каждого члена (в обратном порядке создания)
3) Выполнить деструктор родительского класса.(если несколько в обратном порядке создания)

Если вы используете виртуальное наследование, тогда все немного отличается, так как порядок построения базового класса не совпадает с обычным. НО Порядок уничтожения ВСЕГДА в порядке, обратном порядку строительства.

1 голос
/ 18 августа 2010

Раздел 12.6.2 / 5:

Инициализация должна выполняться в следующем порядке:

  • Сначала и только для конструктора самого производного класса, как описанониже, виртуальные базовые классы должны быть инициализированы в том порядке, в котором они появляются при первом обходе слева направо по глубине направленного ациклического графа базовых классов, где «слева направо» - порядок появления базового класса.имена в списке базовых спецификаторов производного класса.
  • Затем прямые базовые классы должны быть инициализированы в порядке объявления, как они появляются в списке базовых спецификаторов (независимо от порядка инициализаторов mem).
  • Затем нестатические элементы данных должны быть инициализированы в порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-инициализаторов).- Наконец, выполняется тело конструктора.

[Примечание: порядок декларирования должен обеспечивать уничтожение базовых и дочерних подобъектов в обратном порядке инициализации.]

1 голос
/ 18 августа 2010

Порядок уничтожения - это строительный заказ в обратном порядке.Недавно я создал небольшой инструмент для отображения порядка построения для любой иерархии.Смотрите здесь:

На диаграммах узлы сменьшие числа создаются первый и разрушаются последний .

0 голосов
/ 18 августа 2010

Сначала производная, потом база. Нет разницы в не виртуальных случаях.

Дополнительное примечание. Когда у вас есть наследование и виртуальные методы, вы должны объявить деструкторы как виртуальные, иначе вы можете иметь неопределенное поведение при удалении.

Например, предположим, что Derived получен из Base, и вы выделяете Derived со следующей строкой:

Base *o = new Derived();
delete(o);

Если этот случай встречается в вашем коде, а в Base нет виртуального деструктора, результирующее поведение не определено. Как правило, вызывается только деструктор базы. Деструктор Derived не будет вызван, потому что вы вызываете delete для базового указателя. Тем не менее, программа может аварийно завершить работу. Как только вы попадаете в область неопределенного поведения, все ставки отменяются, а ваш исполняемый код обречен. Для предотвращения хаоса Базовый деструктор должен быть виртуальным.

0 голосов
/ 18 августа 2010

Порядок разрушений если снизу вверх. (от производного до базового)

Краткий ответ: полная противоположность Порядок конструктора.

Длинный ответ: предположим, что "большинство производный "класс D, означающий фактический объект, который был изначально создан был класса D, и это D наследует умножить (и не виртуально) от B1 и B2. Подобъект соответствует наиболее производному классу D запускается первым, затем следуют врачи его не виртуальные базовые классы в обратный порядок декларации. Таким образом порядок деструктора будет D, B2, B1. Это правило применяется рекурсивно; за Например, если B1 наследуется от B1a и B1b и B2 наследуются от B2a и B2b, окончательный порядок - D, B2, B2b, B2a, B1, B1b, B1a.

См. Раздел c ++ faq 25

0 голосов
/ 18 августа 2010

Это противоположный способ, как конструкторы.Так выводится первым.

0 голосов
/ 18 августа 2010

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

Без виртуальных базовых классов производные классы всегда уничтожаются раньше своих базовых классов; это обратный порядок, в котором они построены.

Для самого производного класса сначала создаются виртуальные базовые классы, перед другими базовыми классами и перед самим самым производным классом. Уничтожение происходит в обратном порядке. Это означает, что виртуальная база может быть уничтожена после класса, который является ее производным, если этот класс не является самым производным классом, подлежащим уничтожению. Этого никогда не случится с прямыми базовыми классами.

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