Warum lässt C ++ Zugriffsbeschränkungen für vererbte Basismethoden zu?

9

Zur Frage " Wie erben Sie öffentlich von einer Basisklasse, aber machen Sie einige öffentliche Methoden aus der Basisklasse privat in der abgeleiteten Klasse? ", ich habe eine Anschlussfrage:

Ich kann verstehen, dass der C ++ - Standard einer abgeleiteten Klasse erlaubt, relax Zugriffsbeschränkungen einer geerbten Methode zu umgehen, aber ich kann mir keinen legitimen Anwendungsfall vorstellen, in dem es sinnvoll wäre, Zugangsbeschränkungen einzuführen die abgeleitete Klasse.

Nach meinem Verständnis des Vererbungskonzepts, wenn die Klasse Abgeleitet die öffentliche Klasse Base ist, kann alles, was Sie mit Base tun können, auch mit Abgeleitet geschehen. Wenn man nicht möchte, dass Derived die Schnittstelle von Base erfüllt, sollte man (öffentliche) Vererbung überhaupt nicht verwenden. (In der Tat, wenn ich diese Technik in der Wildnis in ROOT TH2 :: Fill (double) begegnete, war dies ein klarer Fall von Erbschaftsmissbrauch.)

Für virtuelle Methoden sind Zugriffsbeschränkungen in Derived ebenfalls nutzlos, da jeder Benutzer von Derived sie verwenden kann, indem er ein Derived * in eine Base * umwandelt.

Aus meiner Sicht von C ++ - Neulingen sind diese Einschränkungen also irreführend (der Programmierer von Derived könnte annehmen, dass seine virtuelle, jetzt geschützte Methode von niemandem aufgerufen wird, obwohl es tatsächlich so ist) und auch verwirrt. Was ist mit öffentlicher Vererbung gemeint?

Gibt es einen legitimen Anwendungsfall, den ich vermisse?

    
user2247306 03.11.2016, 16:20
quelle

2 Antworten

3

Von Herb Sutter, Guru der Woche # 18 :

  

Richtlinie # 3: Nur wenn abgeleitete Klassen die Basisimplementierung einer virtuellen Funktion aufrufen müssen, machen Sie die virtuelle Funktion geschützt.

Für detaillierte Antwort, lesen Sie bitte meinen Kommentar in den Code geschrieben:

%Vor%     
Danh 07.11.2016, 15:04
quelle
1
  

Nach meinem Verständnis des Vererbungskonzepts, wenn die Klasse Abgeleitet die öffentliche Klasse Base ist, kann alles, was Sie mit Base tun können, auch mit Abgeleitet geschehen.

Dies ist nicht wirklich das Konzept der Vererbung; das ist das Konzept des Polymorphismus. Dies ist insbesondere eine Aussage des Liskow-Substitutionsprinzips. Aber Vererbung kann für verschiedene Dinge in C ++ jenseits von nur Polymorphismus verwendet werden. Jedes Mal, wenn Ihre Basisklasse über nicht virtuelle Methoden oder Datenelemente verfügt, verwenden Sie sie, um Implementierung oder Status in abgeleitete Klassen zu injizieren, nicht nur für Polymorphie. Wenn die Basisklasse keine virtuellen Methoden und keinen virtuellen Destruktor hat, sollte die Klasse nicht polymorph (nicht) verwendet werden können. Sie können eine Basisklasse verwenden, in der weder die Basisklasse jemals instanziiert wird noch jemals ein Zeiger auf eine Basis verwendet wird. Hier ist ein Beispiel:

%Vor%

Was macht diese komische Klasse? Nun, es kann verwendet werden, um eine Schnittstelle in jede Klasse mit einem Datenelement namens data (und einem geeigneten Konstruktor) einzufügen:

%Vor%

Jetzt Bar hat Methoden double und halve . Dieses Muster wird als Curiously Recurring Template Pattern (CRTP) bezeichnet. Beachten Sie, dass wir nie Foo<Bar> instanziieren oder einen Zeiger darauf haben. Wir verwenden nur die Schnittstelle, die es bietet, nicht polymorph.

Nehmen wir nun an, jemand möchte Foo verwenden, möchte aber nur double in seiner Schnittstelle, aber nicht halve . In diesem Fall ist es absolut gültig, halve privat im Abgeleiteten zu machen. Schließlich ist die abgeleitete Klasse nur ein bestimmter, nicht polymorpher Typ, der keiner anderen Schnittstelle als dem entspricht, was der Autor will / dokumentiert.

Beachten Sie, dass bei Verwendung von CRTP die Basisklasse normalerweise öffentliche Funktionen bereitstellt und Sie normalerweise öffentlich erben. Der gesamte Vorteil von CRTP in diesem Anwendungsfall besteht darin, dass Sie die Schnittstelle direkt injizieren können; Wenn du die Methoden privat machen oder privat übernehmen möchtest, solltest du Foo<Bar> stattdessen ein Mitglied von Bar sein. Es wäre also eher üblich, in dieser speziellen Situation etwas öffentliches zu machen, anstatt umgekehrt.

    
Nir Friedman 07.11.2016 16:09
quelle

Tags und Links