【问题标题】:Error : base class constructor must explicitly initialize parent class constructor错误:基类构造函数必须显式初始化父类构造函数
【发布时间】:2014-07-02 01:56:34
【问题描述】:

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

}

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

【问题讨论】:

    标签: c++ constructor initialization derived-class


    【解决方案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】:

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

          【讨论】:

          • 这不是一个好的解决方案,因为它允许您构造一个处于未定义状态的parent 实例。如果parent 是一个无法实例化的抽象类,那可能没问题,但事实并非如此。
          【解决方案5】:

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

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

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

          【讨论】:

            猜你喜欢
            • 2019-12-24
            • 2020-09-26
            • 1970-01-01
            • 1970-01-01
            • 2013-11-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-04
            相关资源
            最近更新 更多