错误:基类构造函数必须显式初始化父类构造函数

Error : base class constructor must explicitly initialize parent class constructor

本文关键字:构造函数 初始化 父类 基类 错误      更新时间:2023-10-16

我是c++新手。当我尝试编译下面的代码时,我得到了这个错误

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[]) 
{
}

为什么我得到这个错误?我该如何解决?提前感谢

父类有一个显式构造函数,所以编译器不会给它添加一个隐式的'empty'构造函数。另外,构造函数有一个参数,所以编译器不能生成对它的隐式调用。这就是为什么你必须明确地这样做。

:

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

初始化派生类的对象时,必须首先构造基类部分。如果你没有在派生类的构造函数中调用它的一个构造函数来初始化它,编译器将尝试使用基类的默认构造函数。在您的例子中,没有定义默认构造函数,因为您已经提供了一个自定义构造函数。

要解决这个问题,你必须为基类提供一个默认构造函数,或者直接在派生类的构造函数的初始化列表中调用它的构造函数:

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

冒着重复您得到的错误信息的风险:子类构造函数必须调用其父类的构造函数。

编译器将自动调用父类的默认(无参数)构造函数。如果父类没有默认构造函数,你必须自己显式调用它所拥有的一个构造函数。

编译器必须强制执行这一点,以确保子类从父类继承的功能被正确设置…例如,初始化子进程从父进程继承但不能直接访问的私有变量。即使你的类没有这个问题,你仍然必须遵守规则。

下面是一些使用继承的类中的构造函数的例子:

这很好,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) {}
};

从基类Book派生出MyBook类的另一个例子。现在为基类构造函数提供了带有两个参数的自定义构造函数,因此基类没有默认构造函数。当在主函数内部创建派生类对象时,首先编译器将尝试调用不存在的基类构造函数。因此,基类构造函数需要从派生类构造函数中显式调用,以初始化派生类从基类继承但不能直接访问的任何私有变量(例如标题字符串变量)。正如用户rook提到的,我们需要遵循这些规则。您可以从Alex Allain对初始化列表的详细解释中获得更多详细信息。因此,当没有定义默认构造函数时,以及初始化常量成员时,必须使用初始化列表。他总结——

在运行构造函数体之前,为它的父类,然后为它的字段调用。默认情况下,调用无参数构造函数。初始化列表允许您选择调用哪个构造函数及其参数构造函数接收。

#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;
}

嗨,试着在父类中添加默认构造函数(无参数构造函数),然后编译它。