Базовый класс в списке инициализации конструктора копирования производного класса (C ++) - PullRequest
1 голос
/ 24 ноября 2010

Пусть пример будет таким:

class Base {
  Base (const Base & copyFrom) { globalRegister (* this); }
}

class Derived {
  Derived (const Derived & copyFrom) : Base (copyFrom) {}
}

Я прочитал предложения включить конструктор копирования Base в список инициализации Derived для копирования свойств Base (как в примере).

Тем не менее, у меня есть конструктор копирования Base, передающий себя (* this) другому объекту (для регистрации в этом объекте).Будет ли это тот случай, когда я действительно должен использовать (неявно или явно) конструктор Base (по умолчанию) в списке инициализации конструктора копирования Derived и вызывать конструктор копирования Base только в теле конструктора копирования Derived, когда фактически существует объектчто может быть прикреплено конструктором копирования Base?Иначе - (* this) допустимый объект?

Ответы [ 2 ]

5 голосов
/ 24 ноября 2010

Это был бы тот случай, когда я действительно должен использовать (неявно или явно) конструктор Base (по умолчанию) в списке инициализации конструктора копирования Derived и вызывать конструктор копирования Base только в теле конструктора копии Derived,когда на самом деле есть объект, который может быть присоединен конструктором копирования Base?

С какой стати вы захотите это сделать?
(О, и вы не можете вызвать конструктор копирования базового класса из производного класса body .Только из списка инициализации.)

Иначе - является ли (* this) допустимым объектом?

В тот момент, когда список инициализации базы завершен, все члены базы (и базовые классы) полностью построены.Однако сам класс полностью создается только после завершения его конструктора.
Что более важно, конструктор производного класса еще даже не запущен, поэтому объект еще не является объектом производного класса.

Итак, что бы ни делала эта регистрирующая функция, она должна учитывать, что тип динамического объекта равен base и что его конструктор еще не завершен.(Чтобы быть в безопасности, все, что он может сделать, это хранить адрес объекта где-нибудь.)

1 голос
/ 05 декабря 2010

Просто для справки, поведение указано в § 12.7 2-3 C ++ 03:

2) Чтобы явно или неявно преобразовать указатель (lvalue), ссылающийся на объект класса X, в указатель (ссылку) на прямой или косвенный базовый класс B of X, конструкцию X и конструкцию всех его прямые или косвенные основания, которые прямо или косвенно вытекают из B, должны начаться, а уничтожение этих классов не должно быть завершено, в противном случае преобразование приведет к неопределенному поведению.

this - указатель на Derived. В Base::Base(), this неявно приводится к Base*, что разрешено, потому что началось построение Derived, и у него нет других баз, производных от Base.

§ 12.7 2 продолжается:

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

Наконец, § 12.7 3 также важен:

3) Функции-члены, включая виртуальные функции (10.3), могут вызываться во время создания или уничтожения (12.6.2). Когда виртуальная функция вызывается прямо или косвенно из конструктора (в том числе из mem-initializer для члена данных) или из деструктора, и объект, к которому применяется вызов, является объектом, находящимся в стадии строительства или уничтожения вызываемая функция - это та, которая определена в собственном классе конструктора или деструктора или в одной из его баз, но не функция, переопределяющая ее в классе, производном от класса конструктора или деструктора, или переопределяющая его в одной из других баз классы самого производного объекта (1.8). Если вызов виртуальной функции использует явный доступ к члену класса (5.2.5), а выражение объекта ссылается на объект, находящийся в процессе создания или уничтожения, но его тип не является ни собственным классом конструктора, ни деструктора, ни одной из его баз, результат звонок не определен.

Эти два предложения означают, что экземпляр Derived является полноценным Base, как только начинается конструктор Base, хотя он может находиться в несовместимом состоянии.

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