Nein. Sie können nicht. Vererbung in C++ impliziert eine gewisse Binärkompatibilität in der Praxis.
Eine Problemumgehung folgt. Aber zuerst:
Ein Kreis ist keine Ellipse.
Um genauer zu sein, ist ein veränderbarer Kreis in vielen nützlichen Weisen keine veränderbare Ellipse. Es gibt Operationen, die Sie an einer veränderbaren Ellipse ausführen können, deren Nachbedingungen nicht mit den gleichen Operationen auf einem veränderbaren Kreis übereinstimmen.
Zum Beispiel angenommen, es gibt get/set Haupt/Nebenachse. Eine sinnvolle Nachbedingung auf der Hauptachse besteht darin, dass kleinere Achsen auf einer veränderbaren Ellipse unverändert bleiben. Während Sie die Haupt-/Nebenachse auf einem Kreis setzen können, kann diese Nachbedingung nicht halten!
Nun ist ein unveränderlicher Kreis eine unveränderliche Ellipse. Erst wenn Sie mit der Bearbeitung beginnen, tritt das kovariante/kontravariante Problem auf. Dieses Problem ist nicht auf Rechteck/Quadrat, Ellipse/Kreis, Automobil/LKW-Stil "Spielzeug" OO beschränkt; Eine bearbeitbare Liste von Derived ist keine bearbeitbare Liste von Base, sondern in gleicher Weise. Eine bearbeitbare Liste von Base akzeptiert beliebig Basistyp; Das Gleiche gilt nicht für eine Liste von Derived.
Auf der anderen Seite ist eine unzerstörbare Liste von Derived eine unveränderliche Liste von Base.
Zurück zu Ihrer ursprünglichen Frage, erben die Implementierungen wie diese möglicherweise unklug. Sie können jedoch Daten aus der Logik von der Schnittstelle trennen.
Dann erben Schnittstelle und Logik, während Daten nicht zugeordnet bleiben.
In C++ kann dies mit Vorlagen und CRTP getan werden. Wenn Sie CRTP nicht kennen, ist das folgende unzuverlässig und unlesbar. Ich garantiere keine Gegenleistung.
template<class Self>
struct ellipse_math {
Self* self(){ return static_cast<Self*>(this);}
Self const* self() const { return static_cast<Self const*>(this);}
double get_area() const { /* math using self()->get_major() and self()->get_minor(); */ }
};
struct circle_state {
double m_radius;
double get_major() const;
double get_minor() const;
double get_radius() const;
};
struct ellipse_state {
double m_major, m_minor;
double get_major() const;
double get_minor() const;
};
struct I_ellipse {
virtual double major()const=0;
virtual double minor()const=0;
cirtual double area()const=0;
virtual ~I_ellipse(){};
};
struct I_circle:I_ellipse {
virtual double radius()const=0;
};
template<class Self, class I=I_ellipse>
struct impl_I_ellipse : I {
Self* self(){ return static_cast<Self*>(this);}
Self const* self() const { return static_cast<Self const*>(this);}
virtual double major()const final override { return self()->get_major(); }
virtual double minor()const final override { return self()->get_minor(); }
virtual double area()const final override { return self()->get_area(); }
};
template<class Self, class I=I_circle>
struct impl_I_circle : impl_I_ellipse<Self, I> {
Self* self(){ return static_cast<Self*>(this);}
Self const* self() const { return static_cast<Self const*>(this);}
virtual double radius()const final override { return self()->get_radius(); }
};
struct ellipse :
ellipse_state,
impl_I_ellpise<ellipse>,
ellpise_math<ellipse>
{};
struct circle :
circle_state,
impl_I_circle<circle>,
ellpise_math<circle>
{};
Das ist ziemlich lächerlich in diesem einfachen Fall, aber ich habe mit nicht verwendeten Ellipse Felder in meinem Kreis Umsetzung zu vermeiden, und bekam die ellpise Logik wiederzuverwenden.
Das obige wurde auf einem Telefon getippt, enthält also wahrscheinlich tpyos.
Ehrlich, wenn ich so weit gehen würde, würde ich den ganzen Weg zum SBO-Typ löschen Ellipse-ähnliche und kreisförmige Objekte mit freien Funktionen für den Versand gehen. Weil die Vererbung oben und vtable mehr in die Quere kommen als sie helfen.
Dies ist ein Missbrauch der Vererbung denke ich, ein Kreis kann eine Ellipse mathematisch sein, aber nicht unbedingt programmatisch – StoryTeller
StoryTeller i s richtig: Ihre eigenen Bedenken zeigen deutlich, dass für Sie die Verwendung von Vererbung in der Anwendungsdomäne falsch ist. – user268396
Wenn Sie nicht alle Eigenschaften einer Klasse vollständig erben können, sollten Sie Ihr Design überdenken – WhiZTiM