Gibt es eine Möglichkeit zu verhindern, dass eine Methode in Unterklassen überschrieben wird?

StackOverflow https://stackoverflow.com/questions/17483

  •  09-06-2019
  •  | 
  •  

Frage

Kennt jemand eine Sprachfunktion oder -technik in C++, um zu verhindern, dass eine untergeordnete Klasse eine bestimmte Methode in der übergeordneten Klasse überschreibt?

class Base {
public:
    bool someGuaranteedResult() { return true; }
};

class Child : public Base {
public:
    bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};

Auch wenn es nicht virtuell ist, ist dies dennoch zulässig (zumindest im Metrowerks-Compiler, den ich verwende). Sie erhalten lediglich eine Warnung zur Kompilierungszeit, dass die nicht virtuelle geerbte Funktion X ausgeblendet wird.

War es hilfreich?

Lösung

Ein paar Ideen:

  1. Machen Sie Ihre Veranstaltung privat.
  2. Machen Sie Ihre Veranstaltung nicht virtuell.Dies verhindert jedoch nicht wirklich, dass die Funktion durch eine andere Definition überschattet wird.

Abgesehen davon ist mir keine Sprachfunktion bekannt, die Ihre Funktion so sperrt, dass sie nicht überladen wird und dennoch über einen Zeiger/Referenz auf die untergeordnete Klasse aufgerufen werden kann.

Viel Glück!

Andere Tipps

Wenn Sie das verwenden können final Spezifizierer für virtuelle Methoden (eingeführt mit C++11) können Sie dies tun.Lassen Sie mich zitieren meine Lieblings-Doc-Site:

Bei Verwendung in einer virtuellen Funktionsdeklaration gibt final an, dass die Funktion nicht von abgeleiteten Klassen überschrieben werden darf.

Angepasst an Ihr Beispiel würde das so aussehen:

class Base {
public:
    virtual bool someGuaranteedResult() final { return true; }
};

class Child : public Base {
public:
    bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};

Beim Kompilieren:

$ g++ test.cc -std=c++11
test.cc:8:10: error: virtual function ‘virtual bool Child::someGuaranteedResult()’
test.cc:3:18: error: overriding final function ‘virtual bool Base::someGuaranteedResult()’

Wenn Sie mit einem Microsoft-Compiler arbeiten, schauen Sie sich auch die an sealed Stichwort.

Klingt so, als ob das, was Sie suchen, das Äquivalent der Java-Sprache ist Finale Stichwort das verhindert, dass eine Methode von einer Unterklasse überschrieben wird.

Als Andere hier haben empfohlen, das kann man wirklich nicht verhindern.Es scheint auch, dass dies eher ein Problem ist Oft gestellte Frage.

(a) Ich glaube nicht, dass es die Lösung ist, die Funktion privat zu machen, da dadurch lediglich die Basisklassenfunktion vor der abgeleiteten Klasse ausgeblendet wird. Die abgeleitete Klasse kann immer eine neue Funktion mit derselben Signatur definieren.(b) Die Funktion nicht virtuell zu machen, ist auch keine vollständige Lösung, denn wenn die abgeleitete Klasse dieselbe Funktion neu definiert, kann man die abgeleitete Klassenfunktion immer durch Bindung zur Kompilierungszeit aufrufen, d. h. obj.someFunction(), wobei obj eine Instanz von ist abgeleitete Klasse.

Ich glaube nicht, dass es eine Möglichkeit gibt, dies zu tun. Außerdem würde ich gerne den Grund für Ihre Entscheidung erfahren, abgeleiteten Klassen das Überschreiben von Basisklassenfunktionen zu verbieten.

Zur Klarstellung: Die meisten von Ihnen haben seine Frage falsch verstanden.Es geht ihm nicht um das „Überschreiben“ einer Methode, sondern darum, ob es eine Möglichkeit gibt, das „Verstecken“ zu verhindern oder nicht.Und die einfache Antwort lautet: „Es gibt keine!“.

Hier ist noch einmal sein Beispiel

Die übergeordnete Klasse definiert eine Funktion:

int foo() { return 1; }

Untergeordnete Klasse, die die übergeordnete Klasse erbt, definiert WIEDER dieselbe Funktion (nicht überschreibend):

int foo() { return 2; }

Sie können dies in allen Programmiersprachen tun.Es gibt nichts, was die Kompilierung dieses Codes verhindert (außer einer Einstellung am Compiler).Das Beste, was Sie erhalten, ist eine Warnung, dass Sie die Methode des übergeordneten Elements verbergen.Wenn Sie die untergeordnete Klasse aufrufen und die foo-Methode aufrufen, erhalten Sie 2.Sie haben den Code praktisch gebrochen.

Das ist es, was er fragt.

eine Warnung zur Kompilierungszeit bezüglich des Ausblendens der nicht virtuellen geerbten Funktion X.

Ändern Sie Ihre Compiler-Einstellungen, um einen Fehler anstelle einer Warnung anzuzeigen.

Ich schätze, das, wovor der Compiler Sie warnt, ist verborgen !!Wird es tatsächlich außer Kraft gesetzt?

Der Compiler gibt möglicherweise eine Warnung aus, aber zur Laufzeit wird die übergeordnete Klassenmethode aufgerufen, wenn der Zeiger vom Typ „übergeordnete Klasse“ ist, unabhängig vom tatsächlichen Typ des Objekts, auf das er zeigt.

Das ist interessant.Versuchen Sie, ein kleines eigenständiges Testprogramm für Ihren Compiler zu erstellen.

Ich habe danach gesucht und bin gestern auf diese [ziemlich alte] Frage gestoßen.

Heute habe ich ein nettes C++11-Schlüsselwort gefunden: final .Ich dachte, es könnte für zukünftige Leser nützlich sein.

http://en.cppreference.com/w/cpp/sprache/final

Wenn Sie die untergeordnete Klasse als Typ ihrer übergeordneten Klasse ansprechen, ruft eine nicht virtuelle Funktion die Version der übergeordneten Klasse auf.

dh:

Parent* obj = new Child();

Sofern Sie die Methode nicht virtuell machen, kann die untergeordnete Klasse sie nicht überschreiben.Wenn Sie verhindern möchten, dass untergeordnete Klassen es aufrufen, machen Sie es privat.

C++ macht also standardmäßig das, was Sie wollen.

Der Versuch zu verhindern, dass jemand denselben Namen wie Ihre Funktion in einer Unterklasse verwendet, unterscheidet sich nicht wesentlich vom Versuch zu verhindern, dass jemand denselben globalen Funktionsnamen verwendet, den Sie in einer verknüpften Bibliothek deklariert haben.

Sie können nur hoffen, dass Benutzer, die Ihren Code und nicht den anderer verwenden möchten, sorgfältig darauf achten, wie sie auf Ihren Code verweisen und dass sie den richtigen Zeigertyp oder einen vollständig qualifizierten Bereich verwenden.

In Ihrem Beispiel wird keine Funktion überschrieben.Stattdessen ist es verborgen (es handelt sich um eine Art degenerierten Fall von Überlastung).Der Fehler liegt im Code der untergeordneten Klasse.Wie csmba vorgeschlagen hat, können Sie lediglich Ihre Compiler-Einstellungen ändern (falls möglich).Es sollte in Ordnung sein, solange Sie keine Bibliothek eines Drittanbieters verwenden, die ihre eigenen Funktionen verbirgt.

Technisch gesehen können Sie verhindern, dass virtuelle Funktionen überschrieben werden.Aber Sie werden nie in der Lage sein, mehr zu ändern oder hinzuzufügen.Das ist keine vollständige Hilfe.Verwenden Sie besser einen Kommentar vor der Funktion, wie in FAQ Lite vorgeschlagen.

C++-Methoden sind standardmäßig privat und nicht überschreibbar.

  • Sie können eine private Methode nicht überschreiben
  • Sie können ein nicht überschriebenes nicht überschreiben.virtual Methode

Meinen Sie vielleicht eine Überlastung?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top