C++ Sichtbarkeit beim Überschreiben ändern

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
Antworten
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Moin,

kann mir einer der C++ Experten hier erklären, worin der Sinn besteht, eine öffentliche, virtuelle Methode einer Basisklasse in einer davon abgeleiteten Klasse privat zu überschreiben?

Hier mal ein Beispiel:

Code: Alles auswählen

class PolymorphicPublic
{
public:
    virtual void MakeIt()
    {
        std::cout << "I'll make it so..." << std::endl;
    }
};


class OverridePrivately : public PolymorphicPublic // keep visibility
{
private: // declaration with different visibility!!!
    void MakeIt() override
    {
        std::cout << "I'll make it overidden..." << std::endl;
    }
};
Damit kann ich dann folgendes tun:

Code: Alles auswählen

    PolymorphicPublic *baseObj = new OverridePrivately();
    baseObj->MakeIt();
Aber (natürlich?) folgendes nicht:

Code: Alles auswählen

    OverridePrivately obj;
    //obj.MakeIt() // cannot call it!
Ich zwinge also den Benutzer dazu, die polymorphe Methode *ausschließlich* über die Basisklasse aufzurufen... wozu kann so etwas prinzipiell gut sein? :K
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du hast den Einsatzzweck eigentlich schon ganz gut erkannt. Das wird dann gemacht, wenn nicht direkt auf den abgeleiteten Objekten gearbeitet werden soll. Aus welchen Gründen man auch immer das möchte.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

EyDu hat geschrieben:Aus welchen Gründen man auch immer das möchte.
Und Du hast nicht zufällig dafür Beispiele? :mrgreen: Mir fällt da irgend wie nichts sinnvolles ein... die Intention geht so in Richtung Template Method Pattern... mit dem Unterschied, dass der Aufruf hier ja wirklich an die abgeleitete Klasse geht (und nicht nur an die Basisklasse), allerdings ausschließlich über das Basisklassen-Objekt...

*seufz* C++ ist so... übermächtig! :evil:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Hier ist eine gute Diskussion zu diesem Thema:
http://stackoverflow.com/questions/3970 ... l-function

Wobei mir die Antwort zu Beginn am besten gefällt:
Eine private virtuelle Funktion führt zu Verwirrung, Verwirrung sollte vermieden werden, also sollen private virtuelle Funktionen vermieden werden.

In C++ gilt (wie in Python):

Code: Alles auswählen

print "Nicht alles" + " was geht " + "sollte auch gemacht werden."
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ah... feiner Link, danke!

Wobei ich pure virtuelle private Methoden bezüglich des Template Method Pattern schon ok finde - da machen Sie ja klar, dass man nur bedingt Einfluss auf den Ablauf nehmen kann. (Den dort verlinkten Artikel von Herb Sutter kannte ich auch.)

In meinem Falle gibt es ja einfach nur gar kein "Template" - und dann empfinde ich das schlicht als wenig erhellend!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ja, die Diskussion auf StackOverflow beschreibt es wirklich gut. Wie bei gefühlt der Hälfte aller C++-Idiome geht es um eine saubere Schnittstelle. Das ist auch der einzige bei dem ich es vor Jahren mal gesehen habe: Die Basisklasse ordentlich zu gestalten war nicht möglich, da musste dann die abgeleitete Klasse herhalten.

Ich würde das Feature eher als "gibt es, weil nichts technisches dagegen spricht" einordnen. Benutzen würde ich es, außer das Problem lässt sich nicht mit vernünftigem Umfang anders lösen, wohl nicht. Das Auftauchen wäre doch etwas unerwartet.
Das Leben ist wie ein Tennisball.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Ich halte das von Hyperion gezeigte Bsp. per se für schlechtes Design und kann nur wenige Gründe finden, wo dass zu gebrauchen wäre.

Warum schlechtes Design? Die Basisklasse definiert die Methode public, also als Schnittstelle. Zusätzlich ist sie virtuell und damit vom Implementierungsdetail der Ableitung zur Laufzeit abhängig. Public virtuals sind aufgrund dieser Interface/Implementationsdetail-Vermischung an sich schon problematisch. Nun macht die Kindklasse aus der vormals öffentlichen eine private Methode - Interfacewechsel. Damit bricht das Design mit der "ist-ein" Idee hinter Vererbung. Schlecht. Und weil es virtual ist, ist auch noch die private Kindimplementation über einen Basisklassencast erreichbar. Hmm.

Einziger Anwendungfall der mir für sowas einfällt - Degradierung einer anfangs zu weit gefassten API, welche in der Implementierung zurückgefahren werden soll. Streng genommen ein Verletzung von OOP.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

jerch hat geschrieben:Einziger Anwendungfall der mir für sowas einfällt - Degradierung einer anfangs zu weit gefassten API, welche in der Implementierung zurückgefahren werden soll. Streng genommen ein Verletzung von OOP.
Ja, den Anwendungsfall hatte ich in meinem Post über deinem auch schon angeschnitten. So ein unglückliches Konstrukt kann eben vorkommen, wenn einem nur die Header eines Moduls zur Verfügung stehen, einem die Schnittstelle nicht gefällt und man unbedingt von der Klasse ableiten muss, da die Basis wegen anderer Schnittstellen erhalten bleiben muss.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

In meinem Fall ist das jedoch nicht so - ich vermute hier mal keine Absicht - oder aber Absicht mit falscher Intention... naja, ich werde es mal versuchen aufzuklären :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten