簡體   English   中英

錯誤:基類構造函數必須顯式初始化父類構造函數

[英]Error : base class constructor must explicitly initialize parent class constructor

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

}

為什么我收到這個錯誤? 我該如何解決? 提前致謝

父類具有顯式構造函數,因此編譯器不會向其添加隱式“空”構造函數。 此外,您的構造函數有一個參數,因此編譯器無法生成對它的隱式調用。 這就是為什么你必須明確地這樣做。

這邊走:

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

另一個示例,其中 MyBook 類是從基類 Book 派生的。 現在為基類構造函數提供了一個帶有兩個參數的自定義構造函數,因此基類沒有默認構造函數。 當在 main 函數內部創建了一個派生類對象 new 時,首先編譯器會嘗試調用不存在的基類構造函數。 因此,需要從派生類構造函數中顯式調用基類構造函數來初始化派生類從基類繼承但不能直接訪問的任何私有變量(例如標題字符串變量)。 正如用戶rook 所提到的,我們需要遵循這些規則。 您可以從Alex AllinInitialization Lists的精彩解釋中獲得更詳細的信息。 因此,當沒有定義的 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;
}

嗨,只需嘗試在您的父類中添加默認構造函數(無參數構造函數)然后編譯它。 希望這可以解決您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM