Als Java-Entwickler noch C/C++ dazulernen: Chancenlos?
-
dot schrieb:
Was genau ist der Sinn davon, ein Dokument von Filename erben zu lassen!?
Das ist so nie geschrieben worden.
BitmapDocument erbte von Document, Filename und Bitmap.
Es ist auch nur ein Beispiel. Ich habe zwar die jeweiligen Klassen, aber afair keine Klasse BitmapDocument. Was ich damit fabriziert habe, hätte einen eigenen Artikel zur Erklärung benötigt, also habe ich das nur flott auf BitmapDocument runtergebrochen.
PS: Und der Rest:
dot schrieb:
Xin schrieb:
Beispiel aus meiner Praxis: Ich programmiere eine eigene Programmiersprache, dort gibt es Operatoren (z.B. Addition oder Negierung). Hier stellt sich zum Beispiel unter Umständen die Frage, ob das ein binärer Operator ist.
Was hat die Basisklasse Operator für einen Sinn, wenn du später dann solche Fragen stellst?
Funktionalität hochziehen, die nicht in den einzelnen Operatoren ausgeführt werden muss. Die Frage stellt sich, wenn ein Algorithmus in class Operator für eine bestimmte Sorte von Operatoren anders funktioniert, wenn es ich um einen Binären Operator handelt.
dot schrieb:
Xin schrieb:
Vererbung ist nichts anderes als Aggregation.
Wieso kann ich ein Objekt von abgeleitetem Typ dann wie ein Objekt vom Typ der Basisklasse behandeln? Das widerspricht doch dem Grundgedanken von Aggregation!?
Das hängt sehr stark davon ab, was Du unter Aggregation verstehst.
Aggregation ist eine "Haufen von Zeugs" und sagt nix darüber wer hier welche Rechte hat.
Bei:
struct A { int a; }; struct B : public A { int b; } bi; struct C { A a; int b; } ci;
unterscheiden sich class B und class C überhaupt nicht. Du darfst die Instanz bi überall da reinwerfen, wo Du A reinwerfen darfst und bei C musst Du halt ci.a schreiben.
Am Programm ändert das nichts - es stellt sich nur die Frage, ob Du das betonen möchtest oder nicht.
Eine Aggregation ist beides: die Anhäufung der beiden Membern a und b, jeweils 4 Byte groß. Du kannst lustig hin- und hercasten. Knorr oder Maggie - alles Tütensuppe.
-
Xin schrieb:
dot schrieb:
Was genau ist der Sinn davon, ein Dokument von Filename erben zu lassen!?
Das ist so nie geschrieben worden.
BitmapDocument erbte von Document, Filename und Bitmap.
Erklär mir bitte, wie das sein kann, dass ein BitmapDocument, das von Document, Filename und Bitmap erbt, nicht von Filename erbt!?
Xin schrieb:
dot schrieb:
Xin schrieb:
Beispiel aus meiner Praxis: Ich programmiere eine eigene Programmiersprache, dort gibt es Operatoren (z.B. Addition oder Negierung). Hier stellt sich zum Beispiel unter Umständen die Frage, ob das ein binärer Operator ist.
Was hat die Basisklasse Operator für einen Sinn, wenn du später dann solche Fragen stellst?
Funktionalität hochziehen, die nicht in den einzelnen Operatoren ausgeführt werden muss. Die Frage stellt sich, wenn ein Algorithmus in class Operator für eine bestimmte Sorte von Operatoren anders funktioniert, wenn es ich um einen Binären Operator handelt.
Wenn ein Algorithmus für eine bestimmte Sorte von Operatoren anders funktioniert, dann bedeutet das, dass er nicht für alle Operatoren gleich funktioniert. Damit stellt sich unweigerlich die Frage, wieso das Interface des Algorithmus das Gegenteil behauptet, indem es jeden beliebigen Operator entgegen nimmt. (Siehe auch: http://en.wikipedia.org/wiki/Liskov_substitution_principle)
Xin schrieb:
Bei:
[...]
unterscheiden sich class B und class C überhaupt nicht. Du darfst die Instanz bi überall da reinwerfen, wo Du A reinwerfen darfst und bei C musst Du halt ci.a schreiben.
Das ist nicht das gleiche und funktioniert überhaupt nur, weil C::a public ist.
Wenn du tatsächlich der Meinung bist, dass Vererbung und Aggregation äquivalent sind, dann erklär mir, basierend auf dieser Annahme, bitte den Output von folgendem Programm:
#include <iostream> struct A { }; struct B : public A { int b; }; struct C { A a; int b; }; int main() { std::cout << sizeof(A) << '\n' << sizeof(B) << '\n' << sizeof(C) << '\n'; }
Output (MSVC 11 x64):
1 4 8
-
Na das hat doch jetzt eher was mit Optimierung leerer Basisklassen zu tun. Trotzdem ist fuer mich Vererbung der Ausnahmefall und der eingeschlagene Weg von Xin fuer falsch. Es gibt genug Argumente und Beispiele im Internet, rueckblickend finde ich meinen Verzicht auf Vererbung als gut.
-
dot schrieb:
Xin schrieb:
dot schrieb:
Was genau ist der Sinn davon, ein Dokument von Filename erben zu lassen!?
Das ist so nie geschrieben worden.
BitmapDocument erbte von Document, Filename und Bitmap.
Erklär mir bitte, wie das sein kann, dass ein BitmapDocument, das von Document, Filename und Bitmap erbt, nicht von Filename erbt!?
Keine Ahnung wie das sein sollte, wie ich schon schrieb: BitmapDocument erbte von Filenamen.
Document und Filename sind Basisklassen, die grundlegende Konzepte anbieten, BitmapDocument ist die Arbeitsklasse, die diese dann zusammenführt und nutzt.
Ich denke, Du verwechselst hier Document und BitmapDocument. Daher auch die Erklärung auf die Frage, die Du vermutlich stellen wolltest.Alles andere ist bereits erklärt und ich sehe keinen Grund, hier in die Endlosschleife zu gehen.
dot schrieb:
Xin schrieb:
Funktionalität hochziehen, die nicht in den einzelnen Operatoren ausgeführt werden muss. Die Frage stellt sich, wenn ein Algorithmus in class Operator für eine bestimmte Sorte von Operatoren anders funktioniert, wenn es ich um einen Binären Operator handelt.
Wenn ein Algorithmus für eine bestimmte Sorte von Operatoren anders funktioniert, dann bedeutet das, dass er nicht für alle Operatoren gleich funktioniert. Damit stellt sich unweigerlich die Frage, wieso das Interface des Algorithmus das Gegenteil behauptet, indem es jeden beliebigen Operator entgegen nimmt...
Weil es eben nicht nur ein Interface ist, sondern eine Ableitung. Das ist ja gerade der Vorteil der Mehrfachvererbung zum Interface.
Das bedeutet eben, dass Operator Algorithmen anbieten kann, die entsprechend des Interfaces von Operator etwas ausrechnen, was für jeden beliebigen Operator funktioniert.dot schrieb:
Xin schrieb:
Bei:
[...]
unterscheiden sich class B und class C überhaupt nicht. Du darfst die Instanz bi überall da reinwerfen, wo Du A reinwerfen darfst und bei C musst Du halt ci.a schreiben.
Das ist nicht das gleiche und funktioniert überhaupt nur, weil C::a public ist.
Ui, eine Tatsachenbehauptung! Das deutet erstmal deutlich auf eine Meinungsverschiedenheit hin. Wie überraschend.
Wäre es nicht public, wäre es eine andere Semantik. Es funktioniert nicht "nur weil", sondern "genau deswegen, weil" es public ist. Ganz andere Perspektive.
Dies hier führt in eine lange, langweilige Diskussion über den jeweiligen Vergleichsoperation, die mit dem Ergebnis endet, dass Du sagst, dass man das so nicht machen darf und ich frage Dich, wer das Dogma aufgestellt hat und warum mich das interessieren soll und so geht das hin und her und wir landen wieder bei dem wichtigen Punkt, den Du nicht mitzitiert hast: Der Abstimmung auf einen gemeinsam akzeptierte Vergleichsoperation:
Xin schrieb:
Das hängt sehr stark davon ab, was Du unter Aggregation verstehst.
Aggregation ist eine "Haufen von Zeugs" und sagt nix darüber wer hier welche Rechte hat.
Also sparen wir uns das böse Blut, am Ende tun wir eh, was wir jeweils für richtig halten.
Ich muss nachher sowieso langsam mal den ganzen Kram hier raussortieren, denn ich befürchte, dem armen Threadstarter haben wir schon längst irrtümlich und fälschlich vermittelt, dass es chancenlos ist, sinnvoll C++ zu lernen, wenn nichtmals C++-Entwickler sich über Grundlagen einig werden.
-
knivil schrieb:
Na das hat doch jetzt eher was mit Optimierung leerer Basisklassen zu tun. Trotzdem ist fuer mich Vererbung der Ausnahmefall und der eingeschlagene Weg von Xin fuer falsch. Es gibt genug Argumente und Beispiele im Internet, rueckblickend finde ich meinen Verzicht auf Vererbung als gut.
Obgleich dieses Verhalten gemeinhin als "Empty Base Optimization" bekannt ist, handelt es sich dabei imo um viel mehr als eine Optimierung. Die Tatsache, dass diese Optimierung möglich ist, illustriert genau den fundamentalen Unterschied zwischen Vererbung und Aggregation.
Ein Objekt ist etwas, das von anderen Objekten unterschieden werden kann, d.h. es ist eindeutig identifizierbar.
Ein Objekt der Klasse A muss eine Größe > 0 haben, da dies sonst bedeuten würde, dass mehr als ein Objekt den selben Platz einnehmen könnte und die Objekte nichtmehr unterscheidbar wären. Gleichermaßen muss das Subobjekt a eines Objektes der Klasse C eindeutig identifizierbar sein, da es sich ja um ein von einer Instanz von C verschiedenes Objekt handelt. Jedes Objekt der Klasse B ist dagegen allerdings auch ein Objekt der Klasse A und kein separates Objekt...Xin schrieb:
dot schrieb:
Xin schrieb:
dot schrieb:
Was genau ist der Sinn davon, ein Dokument von Filename erben zu lassen!?
Das ist so nie geschrieben worden.
BitmapDocument erbte von Document, Filename und Bitmap.
Erklär mir bitte, wie das sein kann, dass ein BitmapDocument, das von Document, Filename und Bitmap erbt, nicht von Filename erbt!?
Keine Ahnung wie das sein sollte, wie ich schon schrieb: BitmapDocument erbte von Filenamen.
Document und Filename sind Basisklassen, die grundlegende Konzepte anbieten, BitmapDocument ist die Arbeitsklasse, die diese dann zusammenführt und nutzt.
Ich denke, Du verwechselst hier Document und BitmapDocument. Daher auch die Erklärung auf die Frage, die Du vermutlich stellen wolltest.Alles andere ist bereits erklärt und ich sehe keinen Grund, hier in die Endlosschleife zu gehen.
Stimmt, sry, ich wollte eigentlich nach dem Sinn fragen, ein Dokument von Filename abzuleiten und dachte dabei konkret an das BitmapDocument.
-
dot schrieb:
knivil schrieb:
Na das hat doch jetzt eher was mit Optimierung leerer Basisklassen zu tun. Trotzdem ist fuer mich Vererbung der Ausnahmefall und der eingeschlagene Weg von Xin fuer falsch. Es gibt genug Argumente und Beispiele im Internet, rueckblickend finde ich meinen Verzicht auf Vererbung als gut.
Das ist eben nicht einfach nur eine Optimierung, sondern zeigt genau den fundamentalen Unterschied auf.
Ein Objekt ist etwas, das von anderen Objekten unterschieden werden kann, d.h. es ist eindeutig identifizierbar. Ein Objekt der Klasse A muss eine Größe > 0 haben, da dies sonst bedeuten würde, dass mehr als ein Objekt den selben Platz einnehmen könnte und die Objekte nichtmehr unterscheidbar wären. Gleichermaßen muss das Subobjekt a eines Objektes der Klasse C eindeutig identifizierbar sein, da es sich ja um ein von einer Instanz von C verschiedenes Objekt handelt. Jedes Objekt der Klasse B ist dagegen allerdings auch ein Objekt der Klasse A und kein separates Objekt...
Ich mag Deine Argumentation, weil sie zeigt, dass hier eine technischer Unterschied vorliegt. Es ist aber ein Spezialfall: das leere Objekt, hier wird ein Trick verwandt, um die Identifizierbarkeit zu gewährleisten.
Sicher, ein Sonderfall reicht, um seine Argumentation zu begründen, doch hier ist der Sonderfall vor allem eine willkürliche Entscheidung des VC für den Sonderfall, was wie knivil richtig sagt.
knivil schrieb:
Na das hat doch jetzt eher was mit Optimierung leerer Basisklassen zu tun.
Würde sich VC nämlich auf eine einheitliche Darstellung leerer Klassen in allen drei Fällen einigen, was durchaus sinnvoll wäre, dann wäre der VC auch im Sonderfall kein Argument für Deine argumentative Darstellung.
knivil schrieb:
Trotzdem ist fuer mich Vererbung der Ausnahmefall und der eingeschlagene Weg von Xin fuer falsch. Es gibt genug Argumente und Beispiele im Internet, rueckblickend finde ich meinen Verzicht auf Vererbung als gut.
Damit hat keiner ein Problem. Genauso halte ich mein Herangehen für vorteilhaft und baue das weiter aus.
Allerdings wäre ich dankbar, wenn Du mir diese Argumente als PM zur Verfügung stellen könntest, da ich meine Programmiersprache sehr stark auf Vererbung aufbaue und gerne überprüfe, ob ich etwas übersehen habe.Sollte das also nicht nur eine argumentenverstärkende aber leere Worthülse gewesen sein, wäre ich für einen konstruktiven Beitrag dankbar.
-
Xin schrieb:
Ich mag Deine Argumentation, weil sie zeigt, dass hier eine technischer Unterschied vorliegt. Es ist aber ein Spezialfall: das leere Objekt, hier wird ein Trick verwandt, um die Identifizierbarkeit zu gewährleisten.
Sicher, ein Sonderfall reicht, um seine Argumentation zu begründen, doch hier ist der Sonderfall vor allem eine willkürliche Entscheidung des VC für den Sonderfall, was wie knivil richtig sagt.
Es ist eben nicht einfach nur ein technischer Unterschied, sondern ein prinzipieller und der Spezialfall sollte als Illustration dienen. Der Punkt ist nicht, dass ein bestimmter Compiler hier ein anderes Layout generiert (was jeder brauchbare moderne Compiler tun wird). Der Punkt ist, dass ein Compiler hier ein anderes Layout generieren kann, eben weil es sich um zwei rein konzeptionell fundamental verschiedene Dinge handelt. Vererbung modelliert eine "ist-ein" Beziehung (B ist ein A) und Aggregation eine "hat-ein" Beziehung (C hat ein A) und das sind eben zwei völlig orthogonale Konzepte (ein Auto hat vier Räder, aber es ist kein Rad vs. ein Schiff ist ein Fahrzeug aber es hat keine Räder)...
-
dot schrieb:
Es ist eben nicht einfach nur ein technischer Unterschied, sondern ein prinzipieller und der Spezialfall sollte als Illustration dienen. Der Punkt ist nicht, dass ein bestimmter Compiler hier ein anderes Layout generiert (was jeder brauchbare moderne Compiler tun wird).
Er kann den Unterschied so generieren, dass er für Deine Argumentation nicht passt.
Die beiden Argumentationslinien sind orthogonal -> das eine eignet sich nicht um das andere zu begründen. Es trifft sich nur zufälligerweise in dem einen Punkt, den Du aufgezeigt hast.dot schrieb:
Der Punkt ist, dass ein Compiler hier ein anderes Layout generieren kann, eben weil es sich um zwei rein konzeptionell fundamental verschiedene Dinge handelt. Vererbung modelliert eine "ist-ein" Beziehung (B ist ein A) und Aggregation eine "hat-ein" Beziehung (C hat ein A) und das sind eben zwei völlig verschiedene Konzepte (ein Auto hat vier Räder, aber es ist kein Rad vs. ein Schiff ist ein Fahrzeug aber es hat keine Räder)...
Jaja, hatten wir alles schon.
Du hast das Dogma gut verinnerlicht. Ein Fahrrad hat zwei Räder. Ein Fahrrad ist ein Zweirad. Ein Motorrad ist ein Zweirad.
Wieviele Räder hat eigentlich ein Zweirad? Natürlich keine, da ein Fahrrad zwei Räder hat und ein Zweirad ist. Hätte ein Zweirad zwei Räder, hätte ein Fahrrad ja vier...
Hmm... jetzt wird's wieder kompliziert...Alles eine Frage der Perspektive. Du darfst Perspektiven wechseln und das auch modellieren. Am Schluss sollten aber am Fahrrad wie auch Zweirad genau zwei Räder sein. Ob es jetzt zwei Räder hat oder ein Zweirad ist, ist dabei Geschmackssache. Falsch ist aber keins davon, denn es kommt das gleiche raus, nur bei vier Rädern ist was schief gelaufen.
Interessant wird es nur, wenn das Fahrrad ein Zweirad ist, das heimlich ein drittes Rad versteckt hat. Dann "hat es" ein privates Rad... oder ist ein DrittesRadVerstecker... man weiß es nicht
-
Neil deGrasse Tyson schrieb:
The good thing about science is that it's true whether or not you believe in it.
-
Alles eine Frage der Perspektive.
Nein, dein Fahrradbeispiel ist falsch.
Falsch ist aber keins davon, denn es kommt das gleiche raus
Die Richtigkeit am Ergebnis messen, ist ebenfalls falsch und missachtet die Logik.
-
knivil schrieb:
Na das hat doch jetzt eher was mit Optimierung leerer Basisklassen zu tun. Trotzdem ist fuer mich Vererbung der Ausnahmefall und der eingeschlagene Weg von Xin fuer falsch. Es gibt genug Argumente und Beispiele im Internet, rueckblickend finde ich meinen Verzicht auf Vererbung als gut.
Denk ich nicht, für die Optimierung eine nicht genutzten Aggregation/Komposition ist mindestens eine Whole program optimization notwendig, die dann die binär Kompatibilität brechen würde. Stelle sich einer vor, was passiert, wenn man Objekte mit der optimierte Funktion und danach unoptimierte Funktion verwendet. IMO wird das richtiger Datenchaos.
Übrings ist die Ausgabe von GCC identisch.
-
knivil schrieb:
Alles eine Frage der Perspektive.
Nein, dein Fahrradbeispiel ist falsch.
Na, dann freue ich mich auf eine spannende Mail von Dir.
knivil schrieb:
Falsch ist aber keins davon, denn es kommt das gleiche raus
Die Richtigkeit am Ergebnis messen, ist ebenfalls falsch und missachtet die Logik.
Always listen to experts.
They tell you what can't be done and why.Then do it.
(Colin Plumb, wenn ich mich recht entsinne)Ich denke, ich bewege mich durchaus in den Grenzen der Logik. Zumindest programmiere ich so seit einigen Jahren, forciere das auch und komme damit sehr gut voran.
Es gibt hier einen klaren Unterschied: Während ich ein sowohl als auch akzeptiere und beide Methoden gerne nutze, wie sie sich als praktisch erweisen, legst Du Dich auf eins fest.
Wenn Dir das lieber ist, ist das für mich in Ordnung. Aber es wäre schon schön, wenn Du mir entweder irgendwas Inspirierendes mitgeben kannst oder Deine Behauptungen vielleicht argumentativ etwas untermauen könntest. (Mail?)Ansonsten danke ich Dir für die informative Wiederholung bekannter Dogmen und kann weiterhin alles "falsch" machen.
-
Ist dir eigentlich schonmal der Gedanke gekommen, dass du möglicherweise deinem eigenen Dogma unterliegst?
-
dot schrieb:
Ist dir eigentlich schonmal der Gedanke gekommen, dass du möglicherweise deinem eigenen Dogma unterliegst?
Ich unterliege vermutlich vielen Dogmen. Es fiel mir erstmals auf, als man mir Java beibrachte und mir ganz selbstverständlich Dinge erklärte, die ich für absoluten Schwachsinn halte und die Profs ausquetschte und die auch meinten, dass ich falsch liege - aber auch keine Erklärung hatten, warum ich falsch liege.
Die Vermeidung von Mehrfachvererbung ist eins solches Dogma, dem ich nicht mehr unterliege. Übrigens nicht wegen Java, sondern dank diesem Forums, wo man mir dogmatisch erklärte, dass Mehrfachvererbung böse ist und ich das so nicht einsah. Also argumentierte ich dagegen. Damals benutzte ich Mehrfachvererbung aber auch nicht so häufig wie heute. Aber mir fiel in der Diskussion auf, dass das eigentlich ein geiles Feature ist, dem ich viel zu wenig Beachtung geschenkt habe. Da fiel mir auf, wie blödsinnig dieses Dogma ist und ich begann damit rumzuexperimentieren.
Sehr praktisches Feature.
Natürlich unterliege ich Dogmen. Wenn ich an meinem Compiler schreibe und nicht daran gebunden bin, was die Sprache mir offenbar vorgibt, kann ich auch mit Konstrukten spielen, die in C++ nicht üblich sind. Und auf einmal fällt einem auf, dass man ganz selbstverständlich Dinge hinnimmt, obwohl es eigentlich keinen Grund dafür gibt. Es muss nur einer irgendwann mal für wichtig empfunden worden sein und der hat was gesagt und die Welt käut es wieder.
Sehr schön fand ich die Begründung, warum C# kein Const-Correctness unterstützt. Warum das im Design fehlt, hat der C#-Entwickler beschrieben. Und wenn der das sagt, dann ist vollkommen klar, dass ich als Const-Correctness-Fanatiker ja wohl nur ein Spinner bin. Der C#-Entwickler hat das ja wohl klar begründet, dass Const-Correctness Schwachsinn ist.
Und hier bin ich halt der Spinner mit der Mehrfachvererbung.
-
a => b, b (das Ergebnis) ist wahr, leider kann ich nichts ueber a sagen.
Ein Fahrrad hat zwei Räder. Ein Fahrrad ist ein Zweirad.
Hier stellst du die Schlussfolgerung an den Anfang. Richtig ist: Ein Zweirad hat 2 Raeder und ein Fahrrad ist ein Zweirad. Daraus folgt ein Fahrrad hat 2 Raeder. Einfache Deduktion aus Praemisse + Gesetz.
Mathematisch: has_a-Beziehung entspricht Praedikaten und is_a-Beziehung entspricht der Teilmengenbeziehung. Obiges Beispiel: Zweirad ={ x | hat_zwei_raeder(x) }, Fahrrad = { y Zweirad }.
Genau das steht auch bei Wikipedia:
Liskovsches Substitutionsprinzip schrieb:
Sei q(x) eine beweisbare Eigenschaft von Objekten x des Typs T. Dann soll q(y) für Objekte y des Typs S wahr sein, wobei S ein Untertyp von T ist.
Fuer dich: q = hat_zwei_raeder, T = Zweirad, S = Fahrad.
Das ist Objektorientierung, nix Dogma nur Mathe. Dabei ist der Zugriffsspezifikator public, private oder protected egal (auch wenn es funktioniert, siehe oben). Was du machst ist keine Objektorientierung im Sinne des Erfinders.
Und hier bin ich halt der Spinner mit der Mehrfachvererbung.
Ich kann auch von Tuer zu Tuer rennen und gegenkacken. Dann bin ich auch ein Spinner. Aber mit Logik hat das nichts zu tun und jeder bei klarem Verstand wuerde sich dafuer schaemen.
Alle Argumentation zum Trotz denkst du, richtig zu handeln. Deutlich: Nein! Deine Behauptungen sind ignorant und dumm. Beratungsresitent!
dass man ganz selbstverständlich Dinge hinnimmt, obwohl es eigentlich keinen Grund dafür gibt.
Na weil ich auch nicht 1 + 1 = 2 (natuerliche Zahlen) staendig hinterfrage. Einmal reicht voellig.
Wenn Vererbung der Teilmengenbeziehung entspricht, dann entspricht Mehrfachvererbung dem Schnitt von (Teil)Mengen. Aber wenn er nicht leer ist, dann wurden zwei Typen/Mengen definiert, die nicht disjunkt sind. Bzw. nicht orthogonal... Schlechtes Design. Du hingegen benutzt Mehrfachvererbung als Vereinigung von Mengen, was eben nicht dem zugrundeliegendem Prinzip entspricht.
ich das so nicht einsah
Man ich koennte fast jeden Teilsatz einfach zerreissen. Mathe/Logik ist einfach ... unlogisch?
-
Abgesehen davon passt es hinten und vorne nicht.
Fangen wir mal an,Dokument erbt von Filename
OpenFileDialog erbt auch von Filename
BitmapDocument erbt von Document und Bitmap
Application erbt von Hauptmenu und Dokument und Hauptfenster
Das Hauptfenster erbt von Window, OKButton, CancelButton, Rahmen, ClientAreaSchon kann eine Application nur ein Dokument haben.
Das muss natürlich weggetricksat werden, schlage template<size_t number,typename T> TReingeerbtesAttribut vor, dann kann man mehrere gleichartige reingeerbte Attribute wenigstens anhand einer Nummer ausenanderhalten. char wäre noch besser, weil viel lesbarere und Variablennamen mit mehr als einem Buchstaben hat man noch nie gebraucht.Die Application hat auch einen Dateinamen, also erbst sie direkt einen Dateinamen und indirekt noch einen über das Dokument.
Da muß man doch merken, daß der Ansatz kaputt ist.
Und das macht muir Angst, was ist, wenn man dabei tatsächlich mal Vererbung ausdrücken möchte? Die geht in dem ganzen Müll ja total unter.
-
Ohne hier mitdiskutieren zu wollen, da das eh sinnlos ist, nur ein kleiner Hinweis:
mixins
Der erste Schritt ist natuerlich Mixins mit Mehrfachvererbung zu implementieren, weil es simpel wirkt. Das hat sich aber als nicht so toll rausgestellt und deshalb macht man es lieber so: http://www.drdobbs.com/cpp/mixin-based-programming-in-c/184404445 (mit Templates)
Das ganze ist auch schon wieder 12 Jahre her.
-
knivil schrieb:
Was du machst ist keine Objektorientierung im Sinne des Erfinders.
Das habe zum einen auch nie behauptet und zweitens kannst Du die Aussage genauso wenig belegen, wie ich die (nie getroffene) Aussage, dass es im Sinne des Erfinders ist.
Dafür müssten wir erstmal rausfinden, wer das Design Pattern der objektorientierten Programmierung erfunden hat. Mich interessiert auch nicht die Intention irgendeines Erfinders, der sitzt schließlich nicht vor meinem Quelltext.
Interessanterweise hat der Erfinder aber auch private und protected-Ableitungen in C++ vorgesehen. Die Privaten Ableitungen nutze ich nicht, weil ich dann auch klar rausstellen möchte, dass eine Variable abgeschirmt ist.
Da Du den Erfinder von OOP so gut kennst, würde mich mal dessen Intention dazu interessieren.OOP löst ein Problem. Ich löse Probleme. Und um Probleme zu lösen, kann man sich einschränken lassen oder nicht. Und wenn ich Dinge anders modellieren möchte als Du oder Volkard das für richtig halten, so ist das nicht gleichbedeutend mit 'falsch', es entspricht lediglich nicht dem Lehrbuch.
Es hat sich aber für mich als praktisch erwiesen. Das ist erwähnenswert und genausowenig falsch, wie OOP zu Zeiten, als OOP noch ein synonym für Unsinn war.
Ich will kein Lehrbuch schreiben, ich will Probleme lösen.Liskovsches Substitutionsprinzip... sicher, dass Du das als Argument gegen Mehrfachvererbung anbringen möchtest?
Lieber Knivel, wie ich Deinen Wunsch nach Lehrbuch-Programmierung respektiere und dagegen nicht argumentiere, weil ich genauso gut weiß, dass das auch funktioniert, wäre es durchaus nicht zuviel verlangt, wenn Du akzeptierst, dass das Lehrbuch nicht für alle Menschen eine Bibel darstellt und andere Menschen zum Teil andere Wege gehen und damit gut klarkommen.
volkard schrieb:
Abgesehen davon passt es hinten und vorne nicht.
Fangen wir mal an,Dokument erbt von Filename
OpenFileDialog erbt auch von Filename
BitmapDocument erbt von Document und Bitmap
Application erbt von Hauptmenu und Dokument und Hauptfenster
Das Hauptfenster erbt von Window, OKButton, CancelButton, Rahmen, ClientAreaSchon kann eine Application nur ein Dokument haben.
Dein Posting zeigt zwei Dinge: Erstens, dass Du Dir Dinge zusammengefasst hast, die hier nicht geschrieben wurden, die in Deinen Augen nicht passen. Was hat das mit mir zu tun!? Woher kommt eigentlich OpenFileDialog? Warum sollte Application von Document erben? Das würde nur Sinn ergeben, wenn die Applikation selbst als Dokument aufträte, es also eine Applikation für Applikationen gabe.
Zweitens: In dem Du Dinge falsch zusammenbaust, baust Du Dir kein Argument auf. Du kannst Application von einer Liste von Dokumenten erben lassen, schon ist das semantisch vollkommen in Ordnung.
Dir ist vor allem ein wichtiger Punkt entgangen, den ich schon beschrieb: Wenn Du eine Architektur über Mehrfachvererbung aufbaust, musst Du deutlich präziser typisieren. Das hast du bei den Buttons schon gemacht: Sie sind unterscheidbar.Ich versuche es erneut und ich arbeite mit Beispielen(!). Beispiel heißt einfaches und für ein Posting kleines Anschauungsobjekt, nicht zwangsläufig der perfekte Fall, aber geeignet um eine Idee zu transportieren, wenn man sich für die Idee interessiert und statt sofort versucht, alles abzustreiten erst die Möglichkeit akzeptiert, dass es eine Idee sein könnte.
Nehmen wir eine Linie. Eine Linie kann man modellieren als ein Objekt, das zwei Punkte hat. Wir definieren also Punkt und Linie, packen zwei Punkte in die Klasse Linie, die wir mit Startpunkt und Endpunkt ansprechen und fertig.
Mache ich das über Mehrfachvererbung, so muss ich mehr definieren: Ich kann ja nicht zweimal von Punkt ableiten. Ich muss also Typen definieren, die ich von Punkt ableite, aber unterscheidbar sind: Startpunkt und Endpunkt. Herzlich Willkommen im Diamanten. Es ist aber nicht das Diamant-Problem, es ist das Diamant-Feature. Diamant-Feature? Schonmal gehört? Steht in keinem Lehrbuch drin, weil der Diamant ist was böses in der Programmierung. So etwas darf man nicht als Feature beschreiben. Warum darf ich die logischen Eigenschaften denn eigentlich nicht nutzen? Weil in einem Lehrbuch steht, dass der Diamant Böse ist? Ist hier schon einer vom Wichsen blind geworden, oder was?
Also Diamant-Feature.
Welchen Sinn macht das Ganze? Ich muss nun "umständlicher" auf die Koordinaten zugreifen:
line.Startpunkt::x statt line.Startpunkt.x
Ist jetzt nicht der riesen Unterschied, oder? Es passiert intern auch nichts anderes, es ist ja auch nichts anderes: Es ist eine Aggregation, die über Mehrfachvererbung modelliert wurde.
Ich wurde lediglich genötigt, den Membernamen über Typnamen zu modellieren.Ich kann nun aber Funktionen schreiben, die sich ausschließlich mit dem Startpunkt ODER mit dem Endpunkt beschäftigen und das auch in der Signatur zum Ausdruck bringen. Ich muss jetzt auch nicht aufpassen, dass ich die beiden Punkte versehentlich vertausche, denn sie haben unterscheidbare Datentypen. Die Information, ob ich mit einem Startpunkt oder Endpunkt arbeite, kann ich viel länger erhalten und bei einer Funktion, die einen Startpunkt verlangt, muss ich nicht darauf hoffen, dass der Entwickler auch wirklich line.Startpunkt reinwirft, er wirft einfach das komplette Objekt rein und der Compiler greift das richtige Objekt raus. Als Entwickler bin ich überhaupt nicht mehr in der Lage, den falschen Punkt in die Funktion zu werfen (allerdings müssen Konstruktoren ggfs. explicit sein).
Ich sehe das als Vorteil. Das ist von C++ nicht unbedingt optimal unterstützt, es ist schließlich kein Weg aus dem Lehrbuch. Oder umgekehrt: Vielleicht ist das Lehrbuch auch einfach der üblichen Benutzung von Strukturen in der Historie der Programmiersprachen angelehnt. Wäre auch eine Möglichkeit. Wurde das erste Lehrbuch zur OOP eigentlich geschrieben, bevor der erste OOP gemacht hat oder wurde erst gegen gängige Programmierrichtlinien verstoßen und dann ein Buch geschrieben!?
Ein Lehrbuch ist ein Aggregation von Papier, seine Existenz ist kein Beweis, dass da der Weisheit letzter Schluss drinsteht - oder überhaupt irgendetwas sinnvolles. Man darf Lehrbücher und Lehrer in Frage stellen.Aber was ich tue ist modellierbar und man darf sich fragen, was diese Form der Modellierung ändert und ob das in manchen Situationen Vorteile bringt. Es funktioniert. Oder man klammert sich mit Händen und Füßen daran, dass eine andere Perspektive nicht sein darf, wie Knivils es zeigt, weil man ausschließlich von seinem Standpunkt aus auf Fahrräder gucken darf und er glaubt, weil er ein paar mathematische Symbole um seine Worte packt, dass das bedeutet, dass eine andere Perspektive nicht in mathematische Symbole zu kleiden wäre.
∀(Zweirad) : Zweirad ∈ { FahrzeugMitVorderrad } ∧ Zweirad ∈ { FahrzeugMitHinterrad }
Sowas ist doch keine konstruktive Diskussion!? Das ist Schwanzvergleich. Schäufelchenklauen im Sandkasten. Kurz: Kinderkacke. Langweilig.
Ich finde diese Form der Modellierung in vielen Fällen praktisch, ausbaufähig und sehe Potential darin. Und ich werde mich weiter damit beschäftigen. Fertig.
Ich habe mich nie gegen die Programmierung mit Membern ausgesprochen oder gar geschrieben, dass ich zum Programmieren nichts anderes mehr tue als ausschließlich abzuleiten.
Aber ich nutze auch diese Möglichkeit meine Datenstrukturen zu modellieren und wenn ihr Argumente habt, die dagegen sprechen, dann bin ich interessiert die zu hören. Knivils "Das ist falsch" ohne weiteren Kommentar oder sich Ableitungshierarchien auszudenken und darauf basierend Schlussfolgerungen zu ziehen, dass es bei mir vorne und hinten nicht passt, ist keine Argumentation.
Und eine Meinungsverschiedenheit ist akzeptabel, wenn beide Seiten die Toleranz besitzen, das hinzunehmen.
Vielleicht verabschiede ich mich irgendwann von meiner heutigen Ansicht, vielleicht ihr. Das kann man doch so stehen lassen, wenn man sich nicht einig wird, oder?
-
Wo ist bei eine ungerichtet Linie der Startpunkt und wo der Endpunkt?
-