2016-12-22 4 views
4

Im folgenden meinen Compiler sagt, dass mein abgeleiteten Klasse Konstruktor nicht gefunden werden kann:Warum wird mein abgeleiteter Klassenkonstruktor gelöscht?

struct Drink 
    { 
     Drink(const Drink& other); 
    }; 

    struct PepsiMax : Drink {}; 

    int main() 
    { 
     PepsiMax myPepsi;   // <--- the default constructor of PepsiMax cannot be referenced, it is a deleted function 
    } 

I der Standardkonstruktor von Getränke kennt, definiert werden muss, weil ich einen Kopierkonstruktor und der Compiler erstellt wird keine machen Standardkonstruktor für mich. Die Fehlermeldung besagt jedoch, dass es den Standardkonstruktor für meine PepsiMax-Klasse nicht finden kann, von der ich erwartete, dass sie es generiert. Wenn ich den Standardkonstruktor für PepsiMax definiere, dann zeigt es einen Fehler an, der besagt, dass es den Drink-Standardkonstruktor nicht finden kann, was ich erwarte.

Kann ich davon ausgehen, dass es sich auf den Standardkonstruktor von 'Drink' und nicht 'PepsiMax' bezieht, oder habe ich etwas falsch verstanden? Ich erwartete, dass der Compiler einen Standardkonstruktor für 'PepsiMax' erstellt, der den Basisklassenkonstruktor sofort als erstes aufruft.

Bearbeiten: Meine Verwirrung ist geklärt, danke für Ihre Hilfe. Meine Erklärung über meine naive Interpretation des compilergenerierten Konstruktors ist in einer Antwort enthalten.

+1

Es ist, weil Drink keinen Standardkonstruktor hat, nur den Kopierkonstruktor Drink :: Drink (const Drink &), den Sie gerade angegeben haben. Wenn Sie einen Standardkonstruktor haben möchten, fügen Sie Drink() in der Struktur Drink oder PepsiMax() in der Struktur PepsiMax hinzu. – Hugal31

Antwort

2

Das Update ist

struct Drink 
{ 
    Drink() = default; 
    Drink(const Drink& other); 
}; 

Die Anwesenheit des Copykonstruktor vermeidet die automatische Generierung des Standard-Konstruktor zu schreiben (wie Sie wissen). Aber das bedeutet auch, dass der Compiler nicht den Standardkonstruktor für PepsiMax generieren kann, auf dem PepsiMax myPepsi; beruht. Sie müssen es wieder einführen.

+0

* "Das Vorhandensein des Kopierkonstruktors löscht den Standardkonstruktor." * Dies scheint eine irreführende Aussage zu sein, da '' der Defaultkonstruktor löscht '' seit C++ 11 eine spezifische Bedeutung haben kann. – Nawaz

+0

@Nawaz: In der Tat hast du Recht. Ich habe mit der Terminologie herumgespielt. – Bathsheba

+0

@Bathsheba Der Kopierkonstruktor von Drink bedeutet, dass der Compiler den Standardkonstruktor für DRINK nicht automatisch erzeugt, richtig? Aber da ich keine Konstruktoren für PepsiMax definiert habe, sollte es automatisch den Standardkonstruktor für PepsiMax generieren, hätte ich gedacht. Der Fehler besagt, dass der PepsiMax-Konstruktor nicht gefunden werden kann. – Zebrafish

1

Wenn Sie versuchen, eine Variable vom Typ PepsiMax zu erstellen, sollte der Standardkonstruktor dieser Klasse aufgerufen werden. Da es eine Basisklasse (Drink) hat, ruft dieser Standardkonstruktor den Standardkonstruktor Drink auf. Jetzt haben Sie in Ihrer Drink Klasse einen eigenen Kopierkonstruktor deklariert. Dies verhindert, dass der Compiler automatisch einen Standardkonstruktor generiert, daher kann er nicht aufgerufen werden, daher kann auch kein Standardkonstruktor für PepsiMax generiert werden.

Um zu verhindern, dass, sollten Sie explizit den Compiler sagen einen Standardkonstruktor mit

Drink() = default; 

oder realisieren einen eigenen Standardkonstruktor für Drink zu erzeugen.

+0

Das Definieren eines Kopierkonstruktors für Drink stoppt jedoch, dass der Compiler automatisch einen Standardkonstruktor für Drink generiert. Ich habe keine Konstruktoren für PepsiMax definiert, daher erwarte ich, dass der Standardkonstruktor dafür generiert wird. Die Fehlermeldung ist jedoch, dass es den Standardkonstruktor für PepsiMax nicht für Getränk finden kann. – Zebrafish

+1

@TitoneMaurice, der Standardkonstruktor für PepsiMax kann nicht generiert werden - er wäre schlecht gebildet, weil er den Standardkonstruktor von Drink aufrufen muss, der nicht existiert. – SingerOfTheFall

0

Cppreference zitiert dass

Die implizit deklarierte oder Verzug geraten Standardkonstruktors für Klasse T ist undefined wenn: T hat eine direkte oder virtuelle Basis, die einen gelöschten Standardkonstruktor hat, oder es ist nicht eindeutig oder unzugänglich von diesem Konstruktor. wegen der Anwesenheit des Copykonstruktor

In Ihrem Beispiel Drink implizite Standardkonstruktor der Klasse ist gelöscht.

Anschließend wird die implizit deklarierte oder vorbelegt Standardkonstruktors für Klasse PepsiMax ist undefined seine direkte Basisklasse unter Berücksichtigung Drink hat eine gelöschte Standardkonstruktors.

0

Ich möchte nur die Antworten hinzufügen, die andere gemacht haben. Ich verstehe jetzt und will nur meine Verwirrung erklären.

Nun gibt es zwei Möglichkeiten, darüber nachzudenken, wie der Compiler dies für eine naive Person (mich) geht. Die Art, wie ich dachte, ist, dass der Compiler das Äquivalent zum Einfügen des Standardkonstruktors vor Ort und zum Kompilieren ausführt. Wenn dies tatsächlich der Fall ist, sollte die Fehlermeldung dieselbe sein wie wenn ich diese Zeile manuell eingefügt hätte, was eigentlich ein anderer Fehler ist, dass sie den Basis-Standardkonstruktor nicht finden kann, nicht den abgeleiteten Standardkonstruktor.

jedoch ‚offensichtlich‘, was passiert ist, dass der Compiler die zu erzeugt versucht:

Derived() : Base::Base(){} 

Analysiert es versagt Basis :: Base() zu finden, und erzeugen nicht, dass in jeder Zeile, und beschwert sich dann, dass es den abgeleiteten Standardkonstruktor nicht finden kann. Das war offensichtlich für diejenigen, die antworteten. Die Verwirrung hier war, wie der Compiler genau den Standardkonstruktor generiert. Danke, dass Sie mich nur ein bisschen extra aufgeklärt haben.

Verwandte Themen