Подтвердить что ты не робот

Ошибка: конструктор базового класса должен явно инициализировать конструктор родительского класса

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

constructor for 'child' must explicitly initialize the base class 'parent' which does not have a default constructor child::child(int a) {

вот мой класс

#include<iostream>
using namespace std;

class parent
{   
public :
    int x;
    parent(int a);
    int getX();
};

parent::parent(int a)
{
    x = a;
}

int parent::getX() 
{
    return x;
}

class child : public parent
{
public:
    child(int a);   
};

child::child(int a) 
{
    x = a;
}

int main(int n , char *argv[]) 
{

}

Почему я получаю эту ошибку?  Как я могу это решить? Спасибо заранее

4b9b3361

Ответ 1

Родительский класс имеет явный конструктор, поэтому компилятор не добавляет к нему неявный 'пустой' конструктор. Кроме того, у вашего конструктора есть параметр, поэтому компилятор не может создать неявный вызов. Вот почему вы должны делать это явно.

Таким образом:

 child::child(int a) : parent(a)
 {
 }

Ответ 2

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

Чтобы решить эту проблему, вам придется либо предоставить конструктор по умолчанию для базового класса, либо просто вызвать его конструктор в списке инициализаторов производного класса:

child::child(int a) : parent(a)
 {
 }

Ответ 3

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

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

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

Вот несколько примеров конструкторов в классах с использованием наследования:

Это прекрасно, ParentA имеет конструктор по умолчанию:

class ParentA
{
};

class ChildA
{
public:
    ChildA() {}
};

Это не нормально; ParentB не имеет конструктора по умолчанию, поэтому класс ChildB1 должен явно вызвать один из самих конструкторов:

class ParentB
{
    int m_a;

public:
    ParentB(int a) : m_a(a) {}
};

class ChildB1 : public ParentB
{
    float m_b;

public:
    // You'll get an error like this here:
    // "error: no matching function for call to ‘ParentB::ParentB()’"
    ChildB1 (float b) : m_b(b) {}
};

Это хорошо, мы явно вызываем конструктор ParentB:

class ChildB2 : public ParentB
{
    float m_b;

public:
    ChildB2(int a, float b) : ParentB(a), m_b(b) {}
};

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

class ParentC
{
    int m_a;

public:
    ParentC() : m_a(0) {}
    ParentC(int a) : m_a(a) {}
};

class ChildC: public ParentC
{
    float m_b;

public:
    ChildC(float b) : m_b(b) {}
};

Ответ 4

Другой пример, когда класс MyBook происходит из книги базового класса. Теперь для конструктора базового класса предоставляется настраиваемый конструктор с двумя аргументами, поэтому для базового класса нет конструктора по умолчанию. Когда внутри основной функции создается родословный объект производного класса, сначала компилятор попытается вызвать конструктор базового класса, который не существует. Таким образом, конструктор базового класса должен быть явно вызван из конструктора производного класса для инициализации любых частных переменных, которые производный класс унаследовал от базового класса, но не может получить доступ напрямую (например, строковая переменная заголовка). Как упомянуто пользователем rook, мы должны следовать этим правилам. Вы можете получить более подробную информацию из приятного объяснения Списки инициализации Алекс Аллен. Таким образом, списки инициализации необходимы, когда нет определенного конструктора dafault, а также для инициализации постоянных членов. Он суммирует -

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

#include <iostream>
#include <cstdio>

using namespace std;

class Book {
private:
    string title;
protected:
    string author;
public:
    Book(string t, string a) {
        title = t;
        author = a;
    };
    virtual void display() = 0;
};

class MyBook : public Book {
private:
        const string className;
protected:
        int price;
public:
        // Book(t,a) needs to be called before the {} block to initialize, otherwise error (does not match to Book::Book() default constructor will occur)         
        MyBook(string t, string a, int p) : Book(t, a), className("MyClass"), price(p){
        };

        void display() {
            cout << "Title: " << getTitle() << endl;
            cout << "Author: " << author << endl;
            cout << "Price: " << price << endl;
        };
};

int main() {
    string title, author;
    int price;
    getline(cin, title);
    getline(cin, author);
    cin >> price;
    MyBook novel(title, author, price);
    novel.display();

    return 0;
}

Ответ 5

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