Wie für den Zugriff auf geschützte Methode in der Basisklasse von der abgeleiteten Klasse?
Hier ist ein Beispiel des Codes, das mich ärgert:
class Base {
protected:
virtual void foo() = 0;
};
class Derived : public Base {
private:
Base *b; /* Initialized by constructor, not shown here
Intended to store a pointer on an instance of any derived class of Base */
protected:
virtual void foo() { /* Some implementation */ };
virtual void foo2() {
this->b->foo(); /* Compilator sets an error: 'virtual void Base::foo() is protected' */
}
};
Wie Sie Zugang zu den geschützten overrided Funktion?
Vielen Dank für Ihre Hilfe. :o)
- Ich glaube nicht, dass deine Umsetzung ist ganz richtig. Warum muss man eine Instanz der Basis, wie eine member-variable ist? dieser->b->foo() würde versuchen, rufen Sie eine rein virtuelle Methode.
- Dieses Programm sollte nicht kompilieren. Sie kann nicht instanziiert werden eine abstrakte Klasse....Es sei denn
b
verweist auf eine Instanz von einer anderen Klasse abgeleitet ausBase
. - Ich ausgelassen Präzision: Abgeleitet::b Attribut ist vorgesehen zum speichern einer beliebigen Instanz der abgeleiteten Klassen von der Basis
- Siehe auch stackoverflow.com/questions/3247671/... (das ist über die Mitglieder anstelle von Methoden, aber Sie sind nicht sehr unterschiedlich)
- C++ ruft Sie member-Funktionen, nicht Methoden (obwohl einige Leute benutzen den letzteren, aber in meiner Erfahrung, dass führt nur zu sprachlichen Argumente), und die Konzepte sind die gleichen für die member-Funktionen und member-Variablen, also: kopieren Sie der Zugriff auf protected-member in einer abgeleiteten Klasse
Du musst angemeldet sein, um einen Kommentar abzugeben.
Protected-member in einer Basisklasse sind nur zugänglich durch das aktuelle Objekt ein.
Also, Sie dürfen call
this->foo()
, aber Sie sind nicht erlaubt zu rufenthis->b->foo()
. Dies ist unabhängig davon, obDerived
bietet eine Implementierung fürfoo
oder nicht.Der Grund für diese Einschränkung ist, dass es sonst sehr leicht zu umgehen, einen geschützten Zugang. Erstellen Sie einfach eine Klasse wie
Derived
, und plötzlich haben Sie auch Zugriff auf Teile von anderen Klassen (wieOtherDerived
), die angeblich Zugriff von außen geschützt.offsetof
zu tun, aber es ist definitiv nicht um Sicherheit im Sinne von physisch verhindert den Zugriff auf Daten nur zu dokumentieren beabsichtigte Verwendung, die Semantik und die Stabilität der API.Normalerweise würden Sie es tun, mit
Base::foo()
bezieht sich auf die Basis-Klasse für die aktuelle Instanz.Allerdings, wenn Ihr code braucht, um es zu tun die Weise, die Sie versuchen, und es nicht erlaubt ist, dann müssen Sie entweder foo() public oder machen Abgeleitet von einem Freund von Base.
Als eine Lösung deklarieren Sie eine statische geschützte Funktion in
Base
dass leitet den Anruf an die private /protected function (foo
im Beispiel).Können sagen:
Diese Weise, die wir nicht durchbrechen der Kapselung, da die designer von
Base
machen kann, eine ausdrückliche Wahl zu treffen, damit alle abgeleiteten Klassen aufrufenfoo
auf einander, während die Vermeidung zu setzenfoo
in die öffentliche Schnittstelle oder explizit das drehen aller möglichen Unterklassen vonBase
zu Freunden.Zudem ist diese Methode funktioniert unabhängig davon, ob
foo
virtuell ist oder nicht, oder ob es sich um private oder protected.Hier ist ein link zu einer Laufenden version der code oben und hier eine andere version der gleichen Idee, mit ein wenig mehr business-Logik.
Es ist ein bisschen zerbrechlich, aber mit den Klassen, die Sie hier definiert wird, wird dies nicht funktionieren?
Den reinterpret_cast Punkte auf die VTABLE für das Basis-Objekt und ruft es durch diese Mitglieder accessor.
Rufen Sie Basis-Funktionen explizit mit dem scope-operator (Base::foo()). Aber in diesem Fall die Basisklasse nicht definiert foo (es ist rein virtuell), so gibt es eigentlich keine Funktion ausgeführt wird, wenn Sie sagen
this->b->foo();
da b ist ein Zeiger auf Base und nicht Abgeleitet.--- von wo aus?
Können Sie den Zugriff auf ein geschütztes Mitglied nur über erbschaft (abgesehen von den Methoden der gleichen Klasse). Sagen Sie zum Beispiel, Sie haben eine
class Derived1
was erbt vonDerived
, dann ObjekteDerived1
nennen kannfoo()
.EDIT: MSDN-Artikel auf protected access specifier.