Наследование: нет подходящего конструктора по умолчанию - PullRequest
1 голос
/ 11 марта 2012

Я получаю сообщение об ошибке: Нет подходящего конструктора по умолчанию для B. Однако я не понимаю, почему компилятор хочет вызвать конструктор по умолчанию, когда я даю аргументы ii, а DONT не хочет вызывать конструктор по умолчанию.

#include <iostream>
using namespace std;

class A {
    int i;
public:
    A(int ii) { i = ii; cout << "Constructor for A\n"; }
    ~A() { cout << "Destructor for A\n"; }
    void f() const{}
};

class B {
    int i;
public:
    B(int ii) { i = ii; cout << "Constructor for B\n"; }
    ~B() { cout << "Destructor for B\n"; }
    void f() const{}
};

class C:public B {
    A a;
public:
    C() { cout << "Constructor for C\n"; }
    ~C() { cout << "Destructor for C\n"; }
    void f() const {
        a.f();
        B::f();
    }
};

class D:public B {
    C c;
public:
    D(int ii) { B(ii); cout << "Constructor for D\n"; }
    ~D() { cout << "Destructor for D\n"; }
};

int main() {
    D d(47);
}

Ответы [ 5 ]

4 голосов
/ 11 марта 2012

Ваш родительский конструктор должен быть вызван в списке инициализатора:

class D:public B {
    C c;
public:
    D(int ii) : B(ii)/* <- */ { cout << "Constructor for D\n"; }
    ~D() { cout << "Destructor for D\n"; }
};

Обратите внимание на комментарий / * <- * /. Это должно быть изменено. </p>

То, что вы сейчас делаете, - это создание экземпляра B () в вашем конструкторе класса D, который не используется:

D(int ii) { B(ii); /* <- useless*/ }
2 голосов
/ 11 марта 2012
D(int ii) { B(ii); cout << "Constructor for D\n"; }

Вызывает конструктор по умолчанию B. B(ii) создает временный объект B, который разрушается, как только возвращается конструктор D. Короче говоря, он не вызывает конструктор для базового класса объекта, который создается.

Решение:
Чтобы иметь возможность вызывать конкретный конструктор вашего базового класса, вы должны использовать Список инициализаторов членов .

D(int ii) : B(ii)
{
}
1 голос
/ 11 марта 2012

Вы должны понимать, что базовые и членские подобъекты создаются к тому времени, когда вы вводите тело вашего конструктора! То есть, если у вас есть база или элемент, который не имеет значения по умолчанию, вам нужно передать их аргумент в список инициализатора элемента:

D(int ii): B(ii) { std::cout << "constructor for D\n"; }

Объект, который вы построили в своем теле конструктора D, является просто временным объектом, который на самом деле не служит какой-либо цели в вашем случае (хотя временный объект может быть полезен в некоторых случаях).

1 голос
/ 11 марта 2012

Вы создаете D, который получен из B - но ctor D не передает параметр конструктору B, что потребует от B иметь ctor по умолчанию.

Чтобы это исправить,вам обычно нужно написать D, чтобы предоставить параметр для ctor B:

class D : public B { 
    C C;
public:
    D(int ii) : B(ii) { cout << "ctor for D\n"; }
};
1 голос
/ 11 марта 2012

Этот код:

class C:public B
{
    C() { cout << "Constructor for C\n"; }
};

пытается вызвать конструктор B по умолчанию.

Возможно, вы захотите:

class C:public B
{
    C() : B(0) { cout << "Constructor for C\n"; }
};

но это зависит от вашей логики.

Следующее также неверно:

 D(int ii) { B(ii); cout << "Constructor for D\n"; }

должно быть

 D(int ii) : B(ii) { cout << "Constructor for D\n"; }

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

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