2016-07-01 15 views
1

Ich habe gesucht und konnte das Problem nicht finden, das ich erfahre, aber vielleicht weiß ich einfach nicht, wie ich die Frage klar formulieren soll.Warum behandelt ein Elternteil einer Enkelklasse die Initialisierung der Großelternklasse nicht?

Erstens, ich habe nur einen C++ 98 Compiler auf der fraglichen Plattform, also wenn Sie bitte das im Hinterkopf behalten könnten, wenn ich antworte, würde ich es begrüßen.

Lassen Sie mich mein Beispiel geben und die Fehlermeldung erhalte ich:

namespace mal { 

struct Exception : virtual std::runtime_error { 
    Exception(): std::runtime_error("mal exception") {} 
    explicit Exception(const char* msg): std::runtime_error(std::string(msg?msg:"")) {} 
    explicit Exception(const std::string& msg): std::runtime_error(msg) {} 
    virtual ~Exception() throw() {} 
}; // Exception struct 

struct OpenException : virtual Exception { 
    OpenException(): Exception("mal open error") {} 
}; // OpenException struct 

}; // mal namespace 

ich die folgende Fehlermeldung erhalten:

malt.cpp: In constructor ‘mal::OpenException::OpenException()’: 
malt.cpp:18: error: no matching function for call to ‘std::runtime_error::runtime_error()’ 

OpenException Exception erbt, die std :: runtime_error und initialisiert erbt es zu einer Schnur. Warum initialisiert die OpenException-Initialisierungsanweisung Exception("mal open error") std :: runtime_error nicht mit der const char * -Überladung von Exception? Erweitert sich das nicht durch die Vererbungshierarchie?

Wenn C erbt B und B erbt A, scheint es entgegen OO Prinzipien, die C haben würde über die Details der Implementierung von A. wissen

+0

Siehe auch http://stackoverflow.com/questions/38104855/inheritance-wrong-call-of-constructors. –

+0

@RSahu Okay, danke. Meine Frage hatte wirklich nichts mit Mehrfachvererbung zu tun, also hoffe ich, dass Sie mein "Duplikat" hier draußen lassen, falls jemand das gleiche Problem hat wie ich. Mein Problem wurde durch virtuelle Vererbung verursacht *; Aber ohne das zu wissen, würde ich keine gute Suchfolge formulieren, um die Lösung zu finden, die Sie als Duplikat identifiziert haben. – Luv2code

+0

Absolut. Ich mache nichts anderes zu deinem Posten. –

Antwort

1

Wenn Sie eine Klasse haben, dass virtual ly von einer Basisklasse erbt, dann ist die am weitesten abgeleitete Klasse immer direkt für das Aufrufen des Konstruktors für die virtuelle Basisklasse verantwortlich. Dies dient zur Vermeidung von Problemen bei der Vererbung von Diamanten, wobei eine Klasse virtuell von zwei Klassen erbt, die jeweils virtuell von einer gemeinsamen Basis erben. In diesem Fall, welche der beiden Oberklassen sollte die Basisklasse initialisieren?

Beachten Sie, dass dies bei der regulären Vererbung nicht geschieht.

+0

Okay, ich dachte, ich lese, dass virtuelle Vererbung eine Best Practice speziell für den Multiple-Vererbung-Diamond-Effekt ist. Wenn Sie zwei Klassen erben, std :: runtime_error und eine dritte Klasse erbt beide, Ihr 'catch (const std :: exception &) 'wird vermissen und der' (...) 'catch-all wird sich verfangen. Schlagen Sie vor: (1) die virtuelle Vererbung in keiner der beiden Klassen zu verwenden (Exception/OpenException), oder (2) sie nicht in der OpenException zu verwenden, oder (3) die virtuelle Vererbung zu verwenden und sie zu initialisieren std :: runtime_error wieder in OpenException, (4) eine andere Empfehlung? – Luv2code

+0

Ich würde die virtuelle Vererbung nur verwenden, wenn Sie sicher sind, dass Sie die Mehrfachvererbung verwenden werden - und Sie verstehen die Risiken, die sich daraus ergeben. Sie verwenden auch private Vererbung, die in diesen Tagen verpönt ist und wahrscheinlich nicht das ist, was Sie möchten. – templatetypedef

+0

Nein, ich habe nicht vor, Mehrfachvererbung zu verwenden. Ich hatte gerade irgendwo gelesen (CERT vielleicht?), Dass es wegen dieses Diamantenproblems am besten war. Außerdem wollte ich öffentliche Vererbung machen. Ich dachte, da "struct" standardmäßig öffentlich ist, würde es auch für die Vererbung gelten. Ich werde eine explizite "öffentliche" hinzufügen. Vielen Dank! – Luv2code