mikrocontroller.net

Forum: PC-Programmierung pure Interface Hierarchy per se virtual ableiten?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: CppBert3 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: CppBert3 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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,...)

Autor: Clemens L. (c_l)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Virtuelle Ableitungen machen Objekte größer.

Ist es wirklich notwendig, aus den Interfaces eine Hierarchie zu 
bauen?

Autor: CppBert3 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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

Autor: So was haben wir damals auch versucht (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
> 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.

Autor: CppBert3 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: W. W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: CppBert3 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Horst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: W. W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: PittyJ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: W. W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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":
Youtube-Video "Better Code: Runtime Polymorphism - Sean Parent"

Autor: Oliver S. (oliverso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
struct IA
{
    virtual void a() = 0;
};

struct IB : virtual IA
{
    virtual void b() = 0;
};

struct IC : virtual IB
{
    virtual void c() = 0;
};

struct ID : virtual IA, virtual IB, virtual IC
{
    virtual void d() = 0;
};

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

: Bearbeitet durch User
Autor: CppBert3 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.