Вызов конструктора базового класса из тела конструктора подкласса

У меня сложилось впечатление, что это невозможно, см., например: Вызов конструктора базового класса после некоторых других инструкций на С++
Но следующая программа запускает и создает две строки "Person конструктора":

#include <iostream>

class Person
{
public:
    Person() 
    { 
        std::cout << "Constructor Person" << std::endl; }
    };

class Child : public Person
{
public:
    Child() 
    { 
        c = 1; 
        Person(); 
    }
    int c;
};

int main() 
{
    Child child;
    return 0;
}

Первый - это неявный вызов конструктора по умолчанию, который очищается. Как насчет второго - означает ли это, что действие, описанное в названии, является законным? Я использую Visual С++ 2010.

Ответ 1

Ниже приведен фрагмент "Ускоренный С++": "Производные объекты построены:
1. Выделение пространства для всего объекта (члены базового класса, а также производные члены класса);
2. Вызов конструктора базового класса для инициализации части базового класса объекта.
3. Инициализация членов производного класса по указанию инициализатора конструктора. 4. Выполнение тела конструктора производного класса, если оно есть.

Подводя итог ответам и комментариям: вызов конструктора базового класса из тела конструктора подкласса невозможно в том смысле, что # 2 выше должно предшествовать # 4. Но мы все же можем создать базовый объект в производном конструкторе, вызывая, таким образом, базовый конструктор. Это будет объект, отличный от объекта, который строится с исполняемым в данный момент производным конструктором.

Ответ 2

Вызов внутри конструктора дочернего класса не вызывает конструктор базового класса, он создает временный, неназванный и новый объект типа Person. Он будет уничтожен при выходе из конструктора. Чтобы прояснить, ваш пример аналогичен этому:

Child() { c = 1; Person tempPerson; }

За исключением этого случая, временный объект имеет имя.

Вы можете видеть, что я имею в виду, если вы немного измените свой пример:

class Person
{
public:
    Person(int id):id(id) { std::cout << "Constructor Person " << id << std::endl; }
    ~Person(){ std::cout << "Destroying Person " << id << std::endl; }
    int id;
};

class Child : public Person
{
public:
    Child():Person(1) { c = 1; Person(2); }
int c;
};

int main() {
Child child;

Person(3);
return 0;
}

Это приводит к выходу:

Constructor Person 1
Constructor Person 2
Destroying Person 2
Constructor Person 3
Destroying Person 3
Destroying Person 1

Ответ 3

Вы не можете вызывать его из тела дочернего конструктора, но вы можете поместить его в список инициализаторов:

public:
    Child() : Person() { c = 1; }

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

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