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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23647409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:31:04  来源:igfitidea点击:

Error : base class constructor must explicitly initialize parent class constructor

c++constructorinitializationderived-class

提问by charlotte

I am new to c++. When I try to compile the code below , I get this error

我是 C++ 的新手。当我尝试编译下面的代码时,出现此错误

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

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

here is my class

这是我的班级

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

}

Why I am getting this error ? How can I resolve it ? Thanks in advance

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

回答by CiaPan

The parent class has an explicit constructor, so compiler will not add an implicit 'empty' constructor to it. Additionally your constructor has a parameter, so compiler can not generate an implicit call to it. That's why you must do it explicitly.

父类具有显式构造函数,因此编译器不会向其添加隐式“空”构造函数。此外,您的构造函数有一个参数,因此编译器无法生成对它的隐式调用。这就是为什么你必须明确地这样做。

This way:

这边走:

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

回答by Veritas

When you initialize an object of a derived class, the base class part has to be constructed first. If you don't initialize it yourself in the derived class' constructor by calling one of its constructors, the compiler will attempt use the default constructor of the base class. In your case the default constructor is not defined because you already provided a custom constructor.

初始化派生类的对象时,必须首先构造基类部分。如果您没有通过调用其构造函数之一在派生类的构造函数中自行初始化它,编译器将尝试使用基类的默认构造函数。在您的情况下,未定义默认构造函数,因为您已经提供了自定义构造函数。

To solve this you will either have to provide a default constructor for the base class or simply call its constructor in the derived class' constructor's initializer list:

要解决这个问题,您要么必须为基类提供默认构造函数,要么只需在派生类的构造函数的初始值设定项列表中调用其构造函数:

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

回答by Rook

At the risk of repeating the error message you got: a child class constructor must invoke its parent's constructor.

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

The compiler will add an automatic invocation of the parent's default (argumentless) constructor. If the parent does not have a default constructor, you must explicitly invoke one of the constructors it does have by yourself.

编译器将添加对父级默认(无参数)构造函数的自动调用。如果父级没有默认构造函数,则您必须自己显式调用它确实具有的构造函数之一。

The compiler has to enforce this to ensure that the functionality that the child class has inherited from the parent is set up correctly... for example, initialising any private variables that the child has inherited from the parent, but cannot access directly. Even though your class doesn't have this problem, you must still follow the rules.

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

Here are some examples of constructors in classes using inheritance:

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

This is fine, ParentA has a default constructor:

这很好,ParentA 有一个默认构造函数:

class ParentA
{
};

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

This is not fine; ParentB has no default constructor, so ChildB1 class must explicitly call one of the constructors itself:

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

This is fine, we're calling ParentB's constructor explicitly:

这很好,我们显式调用了 ParentB 的构造函数:

class ChildB2 : public ParentB
{
    float m_b;

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

This is fine, ParentC has a default constructor that will be called automatically:

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

回答by Ananda

Another example where a MyBook class is being derived from the base class Book. Now a custom constructor with two arguments are supplied for the base class constructor, therefore there is no default constructor for the base class. When inside the main function, a derived class object novel is created, at first the compiler will attempt to invoke the base class constructor which does not exist. So, the base class constructor needs to be explicitly called from the derived class constructor to initialize any private variables that the derived class has inherited from the base class but can not access directly (e.g. title string variable). As user rookmentioned, we need follow these rules. You can get more detailed information from the nice explanation of Initialization Listsby Alex Allain. So, Initialization Lists are must required when there is no defined dafault constructor and also for initializing constant members. He summarises-

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

Before the body of the constructor is run, all of the constructors for its parent class and then for its fields are invoked. By default, the no-argument constructors are invoked. Initialization lists allow you to choose which constructor is called and what arguments that constructor receives.

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

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

回答by kuttysun

Hi Just try add default constructor in your parent class (No argument constructor) then compile it. Hope this might resolve your problem.

嗨,只需尝试在您的父类中添加默认构造函数(无参数构造函数)然后编译它。希望这可以解决您的问题。