Ich habe x pure abstrakte Klassen (nur virtal ... = 0) die gemeinsam
eine Schnittstellen Hierarchy aufbauen, teilweise gibt es
Mehrfachableitung die aber in Ordnung ist weil das eben nur Interfaces
sind, es gibt definitiv keine Members oder Code der der mehrfach
abgeleitet wird (und wird es auch garantiert niemals geben)
am Ende gibt es dann n echte Klasse welche diese Interfaces
implementieren
durch die Mehrfachableitung bei den Interfaces habe ich jetzt aber
Probleme an die richtigen Pointer/Schnittstellen zu kommen weil ja trotz
der pure-ness noch n mal das selbe Interface in der Hierachie drinn sein
kann
um das ganze homogen zu halten würde ich jetzt z.B. gerne beim
Zusammenbau meiner Interface-Hierarchie immer mit virtual ableiten (auch
als Regel für andere Entwickler) - nur die echte Implementierung ganz
normal - damit wäre das technisch sauber und würde dann z.B. dem C# oder
Java Interface Konzept entsprechen (ich könnte die virtual Ableitung
natürlich auch nur dort machen wo ich sie brauchen aber so eine "mach es
immer so Aussage wäre mir schon lieber")
hier das C# Beispiel:
https://dotnetfiddle.net/O06tsz
das C++ "equivalent"
https://onlinegdb.com/HJheVa9jN
Gibt es Gründe die gegen einen pure abstrakt virtual
Ableitungs-Hierarchie sprechen?
Sorry ganz vergessen:
-Es geht mir nur um eine Lösung für C++
-die pure abstract Interfaces werden als Pointer über DLL-Grenzen
verwendet (mit anderen C++ Kompilern z.B. Intel/Microsoft,...)
>Virtuelle Ableitungen machen Objekte größer.
aber immer nur um Pointer size, oder?
sizeof()
ohne virtual derive + ohne pure virtual = 1 byte
ohne virtual derive + mit virtual = 8 byte
mit virtual derive + mit pure virtual = 16 byte
>Ist es wirklich notwendig, aus den Interfaces>eine Hierarchie zu bauen?
Ja schon - und teilweise kommt es eben zu Mehfachableitung - bin mir
aber noch nicht 1000% sicher
> Ja schon
Nein, wenn du schon bei deinen selbst verursachten Problemen hier
nachfragen musst, wird dir die Komplexität über den Kopf wachsen.
Im Betatest mit realen Aufgaben und realen Anwendern kommen noch einige
Anforderungen, die dein Konzept sprengen. War bisher bei allen Projekten
immer so.
Du musst die Interna so einfach und übersichtlich wie möglich anlegen.
Mit den unvorhersehbaren Anforderungen wird es später sowieso viel zu
komplex.
So was haben wir damals auch versucht schrieb:>> Ja schon>> Nein, wenn du schon bei deinen selbst verursachten Problemen hier> nachfragen musst, wird dir die Komplexität über den Kopf wachsen.
Es ist ja kein Software-Design Problem - sondern erstmal nur eins von
C++, in C#/Java ist das ja ohne irgendwelche Klimmzüge völlig
problemfrei möglich, nur C++ kennt eben kein echtes Interface-Konzept
sondern nur technisch einen Weg das so lala clean aus zu drücken
> Im Betatest mit realen Aufgaben und realen Anwendern kommen noch einige> Anforderungen, die dein Konzept sprengen. War bisher bei allen Projekten> immer so.
Bei böser Mehrfachableitung mit Daten und Code gebe ich dir 100% recht
aber bei reinen Interfaces verstehe ich dich oder deine Bedenken nicht
> Du musst die Interna so einfach und übersichtlich wie möglich anlegen.> Mit den unvorhersehbaren Anforderungen wird es später sowieso viel zu> komplex.
Ich hab hier ein COM-artiges Konzept d.h. Objekt die x Interfaces
implementieren und per DLL als Plugin zur Laufzeit rein kommen können -
und Microsoft macht das nicht per virtual Ableitung sondern per
static_cast<...> in den Factories, das sieht manchmal auch ganz schön
übel aus, mit virtual Ableitung erreiche ich das gleiche ohne die fiesen
static_casts aber bekomme eben fettere Objekte
wenn ich dieses COM-artige Konzept/Plugins nicht hätte gäbe es diese
Interface-Hierarchien gar nicht erst, weil die eben kompliziert sind
I.A. wird viel zu oft Vererbung verwendet, wo auch Komposition
ausreichen würde.
https://en.wikipedia.org/wiki/Composition_over_inheritance
Des Weiteren solltest du dir überlegen, ob du wirklich
Laufzeitpolymorphie mit dynamischen distpach (vtable) brauchst, oder ob
statische Polymorphie nicht angebrachter wäre (Templates). Bei letzterer
werden keine vtables benötigt und es hat keine Kosten zur Lauzeit.
Ich habe mich jetzt gerade noch mal durch diverse Dokus gelesen und fest
gestellt das Microsoft bei COM auch die Mehrfachableitung von
Schnittstellen verbietet - also geben ich euch allen erst mal recht das
ich mir das noch mal genauer überlegen sollte, im Grunde will ich das ja
auch nicht und es fühlt sich die ganze Zeit nicht ganz koscher an - also
Danke für die Kommentare
>Des Weiteren solltest du dir überlegen, ob du wirklich>Laufzeitpolymorphie mit dynamischen distpach (vtable) brauchst, oder ob>statische Polymorphie nicht angebrachter wäre (Templates). Bei letzterer>werden keine vtables benötigt und es hat keine Kosten zur Lauzeit.
Ich habe aber eine abstrakte Schnittstelle die durch eine
DLL-Schnittstelle durch muss, die von unterschiedliche Implementierungen
haben - kann ich da auch mit statischer Polymorphie arbeiten?
CppBert3 schrieb:> https://onlinegdb.com/HJheVa9jN
Deinen Code lese ich so:
IB ist ein IA
IC ist ein IB
ID ist ein IA und ein IB und ein IC
Jetzt versuche ich vergeblich ein Beispiel aus dem Alltag zu finden,
welches man hiermit beschreiben könnte. Mein Gedanke war:
IA = Auto
IB = Peugeot
IC = 206
ID = "Mein Auto"
Dann würde Dein Code bedeuten:
Peugeot ist ein Auto
206 ist ein Peugeot
"Mein Auto" ist ein Auto und ein Peugeot und ein 206
Das macht jedoch keinen Sinn, da ein 206 ja bereits ein Peugeot ist und
dieser wiederum ein Auto. Hierdurch ist "Mein Auto" ja zwei verschiedene
Autos zur gleichen Zeit. Außerdem würde es "Mein Auto" zur Compile-Time
bereits fest als 206 definieren, was eigentlich nicht gewollt sein kann.
---
Wenn ich davon ausgehe, dass Du ein Basisobjekt hast (IA) und diesem
Schritt für Schritt Eigenschaften hinzufügen willst, könnte ich hiervon
ausgehen:
IA = Hammer
IB = Nageleisen
IC = Holzgriff
ID = Hammer mit Nageleisen und Holzgriff
Dann hättest Du tatsächlich ein Objekt modelliert (ID), welches ein
Hammer ist und ein Holzgriff und ein Nageleisen. Bestehend aus einem
Holzgriff der ein Nageleisen ist und ein Hammer, sowie ein Nageleisen
das ein Hammer ist.
---
Damit ich jetzt aber sinnvolles Output geben kann, musst Du die Klassen
(Ia,IB,IC und ID) benennen.
---
> Es ist ja kein Software-Design Problem - sondern erstmal nur> eins von C++, in C#/Java ist das ja ohne irgendwelche> Klimmzüge völlig problemfrei möglich, nur C++ kennt eben kein> echtes Interface-Konzept sondern nur technisch einen Weg das> so lala clean aus zu drücken
Nur weil etwas in XYZ möglich ist, heißt es nicht dass C/C++ schlecht
ist. Und nein, es ist definitiv ein Software-Design-Problem. Meine
Begründung hierfür: Wenn das Design gut ist, kannst Du es in jeder
Programmiersprache ausdrücken.
In Deinem Codebeispiel fehlt mir die "hat ein" Relation. Ich tippe also
darauf, dass Du etwas mithilfe von Vererbung ("ist ein") modellieren
möchtests, was man einfacher und logischer mit "hat ein" ausdrücken
sollte.
Ich diskutiere hier gerne weiter, aber nur wenn Du die Klassen (IA..ID)
mit einem greifbaren Gegenständen benennst.
Horst schrieb:> Dann hättest Du tatsächlich ein Objekt modelliert (ID), welches ein> Hammer ist und ein Holzgriff und ein Nageleisen. Bestehend aus einem> Holzgriff der ein Nageleisen ist und ein Hammer, sowie ein Nageleisen> das ein Hammer ist.Bestehend aus -- Das deutet aber eigentlich eher auf Komposition hin,
als auf Vererbung. Es müsste eher heißen, dass ein und dasselbe Objekt
unterschiedlich aussehen kann/muss, um in verschiedenen Bereichen
eingesetzt zu werden (interface).
https://de.wikipedia.org/wiki/KISS-Prinzip
Sonst wird dir das alles in 2 Jahren um die Ohren fliegen, weil du
selbst mit den komplexen Vererbungen nicht mehr klar kommst.
CppBert3 schrieb:> Ich habe aber eine abstrakte Schnittstelle die durch eine> DLL-Schnittstelle durch muss, die von unterschiedliche Implementierungen> haben - kann ich da auch mit statischer Polymorphie arbeiten?
Das kann ich nicht beurteilen. Aber z.B. eine Frage, die du dir stellen
kannst ist: "Ist zur Kompilierzeit das gewünschte Verhalten bekannt?"
Wenn ja, dann könnte statische Polymorphie auch gehen.
Beispiel: Ein std::vector<int> wird immer int beinhalten und nie struct
foo. Bei einem Listentyp, der mal int, mal struct foo enthalten kann,
und zur Laufzeit mal eine, mal eine andere Funktion/Methode aufgerufen
werden soll, dann brauchst du dynamische Polymorphie.
"Better Code: Runtime Polymorphism - Sean Parent":
https://www.youtube.com/watch?v=QGcVXgEVMJg
Was genau bezweckst du mit ID? IC bringt IA und IB schon mit, wofür
deren nochmalige Vererbung an ID?
Virtuelle Vererbung kann dann sinnvoll wein, wenn es parallel zu den
Interfaces auch eine Hirarchie der Implementierungen dazu gibt.
Oliver
Oliver S. schrieb:> Was genau bezweckst du mit ID? IC bringt IA und IB schon mit, wofür> deren nochmalige Vererbung an ID?
Das war jetzt schnell ein Beispiel für so eine Mehrfach-Ableitung von
Interfaces - und mir ist auch klar geworden das ich solche Ableitungen
definitiv vermeiden möchte, ich probiere im laufe der Woche noch ein
paar Varianten durch und poste (wenn ich dazu komme) noch ein Update mit
was sinnvollem
Danke an alle