Ich habe eine Basisklasse mit einer virtuellen Funktion und möchte diese Funktion in einer abgeleiteten Klasse überschreiben. Gibt es eine Möglichkeit, den Compiler überprüfen zu lassen, ob die in der abgeleiteten Klasse deklarierte Funktion tatsächlich eine Funktion in der Basisklasse überschreibt? Ich möchte ein Makro oder etwas hinzufügen, das sicherstellt, dass ich nicht versehentlich eine neue Funktion deklariert habe, anstatt die alte zu überschreiben.
Nehmen Sie dieses Beispiel:
class parent {
public:
virtual void handle_event(int something) const {
// boring default code
}
};
class child : public parent {
public:
virtual void handle_event(int something) {
// new exciting code
}
};
int main() {
parent *p = new child();
p->handle_event(1);
}
Hier parent::handle_event()
wird statt aufgerufen child::handle_event()
, weil die Methode des Kindes die const
Deklaration verfehlt und daher eine neue Methode deklariert. Dies kann auch ein Tippfehler im Funktionsnamen oder ein geringfügiger Unterschied in den Parametertypen sein. Es kann auch leicht vorkommen, dass sich die Schnittstelle der Basisklasse ändert und irgendwo eine abgeleitete Klasse nicht aktualisiert wurde, um die Änderung widerzuspiegeln.
Gibt es eine Möglichkeit, dieses Problem zu vermeiden? Kann ich dem Compiler oder einem anderen Tool irgendwie sagen, dass er dies für mich überprüfen soll? Irgendwelche hilfreichen Compiler-Flags (vorzugsweise für g ++)? Wie vermeiden Sie diese Probleme?
Antworten:
Seit g ++ 4.7 versteht es das neue C ++ 11-
override
Schlüsselwort:quelle
override
muss in der Definition verwendet werden. Eine Inline-Implementierung ist sowohl Definition als auch Implementierung, das ist also in Ordnung.So etwas wie das
override
Schlüsselwort von C # ist nicht Teil von C ++.Warnt in gcc
-Woverloaded-virtual
davor, eine virtuelle Basisklassenfunktion mit einer Funktion mit demselben Namen, aber einer ausreichend unterschiedlichen Signatur auszublenden, damit sie nicht überschrieben wird. Es schützt Sie jedoch nicht davor, eine Funktion nicht zu überschreiben, weil der Funktionsname selbst falsch geschrieben wurde.quelle
override
in C ++ kein Schlüsselwort erstellt. Dies kann jedoch bedeuten, dass Sie etwas verwenden, das ungültigen C ++ - Quellcode kompilieren kann. ;)override
Funktionen im C # -Stil übernehmen oder verlassen . Ich hatte selten Probleme mit fehlgeschlagenen Überschreibungen und sie waren relativ einfach zu diagnostizieren und zu beheben. Ein Gedanke, dem ich nicht zustimmen werde, ist, dass VC ++ - Benutzer es verwenden sollten. Ich würde es vorziehen, wenn C ++ auf allen Plattformen wie C ++ aussieht, auch wenn ein bestimmtes Projekt nicht portabel sein muss. Es ist erwähnenswert, dass C ++ 0x haben wird[[base_check]]
,[[override]]
und[[hiding]]
Attribute , so dass Sie kann in entscheiden Kontrolle außer Kraft zu setzen , falls gewünscht.override
anscheinend kein Schlüsselwort aus . Nun, kein richtiges Schlüsselwort, sondern eine spezielle Kennung in C ++ 11. Microsoft hat sich genug Mühe gegeben, um einen Sonderfall daraus zu machen und dem allgemeinen Format für Attribute zu folgen undoverride
es zum Standard zu machen :)Kannst du es, soweit ich weiß, nicht einfach abstrakt machen?
Ich dachte, ich hätte auf www.parashift.com gelesen, dass man tatsächlich eine abstrakte Methode implementieren kann. Was für mich persönlich Sinn macht, das einzige, was es tut, ist, Unterklassen zu zwingen, es zu implementieren. Niemand hat etwas darüber gesagt, dass es nicht erlaubt ist, selbst eine Implementierung zu haben.
quelle
BaseClass::method()
) in der abgeleiteten Implementierung (sayDerivedClass::method()
) aufgerufen wird , z. B. für einen Standardwert.In MSVC können Sie das
override
Schlüsselwort CLR verwenden, auch wenn Sie nicht für CLR kompilieren.In g ++ gibt es keine direkte Möglichkeit, dies in allen Fällen durchzusetzen. andere Leute haben gute Antworten gegeben, wie man Signaturunterschiede mit erkennt
-Woverloaded-virtual
. In einer zukünftigen Version könnte jemand eine Syntax wie__attribute__ ((override))
oder eine gleichwertige mithilfe der C ++ 0x-Syntax hinzufügen .quelle
In MSVC ++ können Sie Schlüsselwörter verwenden
override
override
funktioniert sowohl für nativen als auch für CLR-Code in MSVC ++.quelle
Machen Sie die Funktion abstrakt, damit abgeleitete Klassen keine andere Wahl haben, als sie zu überschreiben.
@ Ray Dein Code ist ungültig.
Bei abstrakten Funktionen können keine Körper inline definiert werden. Es muss geändert werden, um zu werden
quelle
Ich würde eine leichte Änderung Ihrer Logik vorschlagen. Es kann funktionieren oder nicht, je nachdem, was Sie erreichen müssen.
handle_event () kann weiterhin den "langweiligen Standardcode" ausführen, aber anstatt virtuell zu sein, muss die Basisklasse an dem Punkt, an dem der "neue aufregende Code" ausgeführt werden soll, eine abstrakte Methode aufrufen (dh muss überschrieben werden) das wird von Ihrer Nachkommenklasse geliefert.
EDIT: Und wenn Sie später entscheiden , dass einige Ihrer abgeleiteten Klassen können nicht brauchen „neuen spannenden Code“ zu schaffen , dann können Sie die abstrakte zu virtuellen ändern und eine leeren Basisklasse Umsetzung dieser „eingefügt“ Funktionalität liefern.
quelle
Ihr Compiler hat möglicherweise eine Warnung, die er generieren kann, wenn eine Basisklassenfunktion ausgeblendet wird. Wenn dies der Fall ist, aktivieren Sie es. Dadurch werden konstante Konflikte und Unterschiede in den Parameterlisten aufgefangen. Leider wird dadurch kein Rechtschreibfehler aufgedeckt.
Dies ist beispielsweise eine Warnung C4263 in Microsoft Visual C ++.
quelle
override
Wenn das Schlüsselwort C ++ 11 mit der Funktionsdeklaration innerhalb der abgeleiteten Klasse verwendet wird, muss der Compiler überprüfen, ob die deklarierte Funktion tatsächlich eine Basisklassenfunktion überschreibt. Andernfalls gibt der Compiler einen Fehler aus.Daher können Sie einen
override
Bezeichner verwenden, um einen dynamischen Polymorphismus sicherzustellen (Überschreiben von Funktionen).quelle