C++ - Exception werfen-Anmerkungen zu virtuellen Funktionen
Sah ich den folgenden code-snippet:
class Foo
{
public:
void virtual func() throw (int, float) = 0;
};
class Bar : public Foo
{
public:
void virtual func() throw(short); //line 1: compile error "
//looser throw specifier"
void virtual func() throw(); //line 2: can compile
void virtual func() throw(float, int); //line 3: can compile
void virtual func() throw(float); //line 4: can compile
void virtual func() throw(int); //line 5: can compile
};
int main(void)
{
return 1;
}
Q1> Was ist der Sinn des
void virtual func() throw (int, float) = 0;
Q2> warum line1 nicht passieren können, den der compiler?
Danke
Du musst angemeldet sein, um einen Kommentar abzugeben.
Lassen Sie uns brechen diese nach unten. Die Erklärung:
verfügt über 2 konstruiert, dass Sie sich Fragen, über. die
=0
Konstrukt teilt dem compiler mit, dass die deklarierten Funktion 'Abstrakt', was sagt der compiler, dass die Funktion muss nicht definiert werden, in derclass Foo
(obwohl es sein kann - aber es ist nicht in der Regel) und dass ein Objekt vonclass Foo
können nicht direkt erstellt werden - entweder als lokaler, globaler oder übernew
. Jedoch, Sie können Zeiger oder Referenzen auf Objekte derclass Foo
. Einige abgeleitete Klasse muss die Funktion überschreiben, wie eine nicht-abstrakte Funktion - Objekte von dieser Klasse kann direkt erstellt werden (, solange es keine andere abstrakte Funktionen, die noch nicht gemacht wurden "konkrete").Den
throw (int, float)
Konstrukt ist eine Ausnahme specifification. Diese sagt dem compiler, dass die Funktion den Vertrag, ist, dass es nur Ausnahmen vom Typint
oderfloat
wenn es eine exception wirft. Wenn die Funktion löst eine andere Art von Ausnahme, dass der compiler ist verpflichtet, Sie zu behandeln, die speziell (durch Aufrufstd::unexpected()
).Nun, wenn Sie versuchen, zu überschreiben, dass die Funktion in einer abgeleiteten Klasse mit der folgenden Erklärung:
Du sagst, dass die Funktion den Vertrag, ist, dass es Ausnahmen vom Typ
short
wenn eine Ausnahme ausgelöst wird. Allerdings werfenshort
ist nicht Bestandteil des Vertrages, der die Funktion überschrieben wird, damit der compiler nicht zulassen.Wenn Sie erklären, die überschreiben, etwa so:
Du sagst, dass das überschreiben zu werfen
float
, das ist Teil des Vertrages, der ursprünglichen Erklärung (wenn es schmeißt einint
nicht den Vertrag zu brechen - der ursprüngliche Vertrag, der nur sagt, dass die Funktion erlaubt die Wurfweiteint
, nicht dass es schon).Den entsprechenden Teil der Norm ist 15.4/3 Exception-Spezifikationen:
Beachten Sie, dass die Norm besagt ausdrücklich, dass eine Ausnahme-Spezifikation ist nicht Teil der Funktion Typ (15.4/12), also ein Funktionszeiger kann, zum Beispiel, zeigen Sie auf Funktionen, die verschiedene exception-Spezifikationen.
Du bist die Definition der gleichen Funktion Unterschrift, viele Male. Die verschiedenen
throw()
Qualifier sind nicht genug, um keine Verwechslungen Funktionen.Den
throw()
qualifier bedeutet einfach, dass die angegebene Funktion ist nur zu erwarten, werfen die Typen aufgelistet, in der Klammer nach dem qualifier. Allerdings bedeutet dies nicht wirklich verhindern, dass die Funktion zu werfen. Eher, wenn die Funktion tatsächlich hat werfen Sie auch alle nicht aufgelistete Arten, das Programm zu beenden.std::unexpected
).Die Funktion, die Sie definiert in der Basisklasse ist so eine Garantie - es kann nur werfen eine
int
oder einefloat
. Ihre Linie 1 ist zu scheitern, weil es bricht die Garantie, indem Sie sagen, wird es werfen eineshort
, die nicht die oben genannten.Den
= 0
im Q1 erklärt, dass jede abgeleitete Klasse, die Sie versuchen, erstellen Sie eine Instanz benötigen, um Ihre eigenen Deklaration und Implementierung dieser Funktion. Die Basisklasse kann auch eine Umsetzung, aber in der Regel nicht.= 0
nicht verhindern, dass eine konkrete implementation in der Basisklasse.Die Bedeutung des namens throw-Anweisungen ist zu erklären, dass eine Funktion kann nur werfen die benannten Ausnahmen, die entweder direkt oder indirekt.
Also die Zeile:
bedeutet, dass was auch immer Klasse erbt dieser Basistyp ist es nur erlaubt zu werfen, entweder ein int-oder ein float. Es kann nicht entweder direkt oder indirekt werfen Sie eine andere Art von Ausnahme oder Objekt. Wenn es das tut, rufen Sie die
unexcepted()
Funktion. Standardmäßig ruft dieterminate()
Funktion. Sie sind berechtigt, reset, dass die Verwendung derset_unexpected
Funktion aber noch.Indem Sie die throw-Anweisungen, um Ihre Schnittstelle, die Sie wirklich selbst die Beschränkung.
std::unexpected
verwendet werden, statt des geworfenen Wert. Ein Kommentar würde das nicht tun.Beim überschreiben einer
virtual
Funktion ohne Ausnahme-Planer, die Sie muss mindestens so restriktiv wie angegeben auf die Funktion, die Sie überschreiben. Dies verhindert, dass der Basis-Klasse " exception-Spezifikation verletzt werden.Als die Basis-Klasse' exception Bezeichner [
throw (int, float)
] nicht erlaubt, eineshort
geworfen werden, die abgeleitete Klasse kann nicht zulassen, dass einshort
geworfen werden. Bei den meisten kann es ermöglichen, eineint
und/oder einefloat
; es kann zulassen, dass entweder nur eine oder keine zu werfen, als eine dieser Möglichkeiten wäre restriktiver als die Ausnahme-Spezifikation die Funktion der Basisklasse.