Interfaces?
-
Auzßerdem is Nr. 1 erweiterbarer (find ich extrem wichtig)
Nr. 2 ist statisch, man kanns nicht schnell ändern (wenn noch andere Dinge hinzukommen, die das ganze schwerer machen, aber das ist ja immer so). Interface ist von Implementation abhängig, da hört man schon das es falsch ist.
mfg
-
Die 2. Methode ist für mich recht unproduktiv.
Weil, was ist, wenn du das Interface erweitern willst/musst,
und es evtl. mehr als eine Implementation gibt (sonst braucht man ja kein Interface)?Devil
-
Ich glaube ich habe den Begriff "Interface" falsch verwendet. Aber es kommt aufs gleiche raus.
Ich hab mich bei der ersten Möglichkeit bloss ein wenig gewundert. Eigentlich sollte public Vererbung ja "ist ein" bedeuten. Da hat es mich gewundert, dass eine Implementation ein Interface sein soll.Und wenn die erste Version sowieso Standard ist, dann werd ich die auf jeden Fall benutzen.
Danke euch allen.
-
Ist das erste aufgrund der vielen virtuellen Funktion sehr viel langsamer als das zweite?
Darauf würde ich nicht wetten, wahrscheinlich ist der Unterschied (fals der Compiler nicht inlined) verschindent klein.
Aber zurück zur eigentlichen Frage. Deine 2 Methoden tuen nicht das gleich bei der ersten handelt es sich um ein Interface, einer Art Declarierung für die es mehrere Implementierungen geben kann. Später kann man auch sehr einfach neue Implementierungen hinzu fügen. Bei der zweiten handelt es sich um das klassiche Model der Declaration im Header und genau einer Definition im Module (zwar in zwei Klassen aufgeteil aber das bring, in diesem Fall, nur Nachteile mit sich).
-
@ ***
OK, jetzt ist mir klar, was genau ein Interface ist. Danke!
Eigentlich ging es mir darum zu verhindern, dass man, wenn man die Klasse sieht, auch deren private Elemente sieht (Nur damit der Code schöner aussieht).
Da das aber alles viel schöner mit der ersten Möglichkeit geht, werd ich die jetzt verwenden.
-
Die zweite Variante nennt sich auch pimpl-Idiom (weil ein Zeiger auf eine Implementierung verwendet wird) und ist IMHO nicht unüblich.
Die erste Variante kenne ich nur aus einer einzigen echten C++-Bibliothek in dieser Form - und die ist eklig zu benutzen. Wenn man wirklich vom geposteten Beispielcode ausgeht, trifft das hier ja auch zu: Der Benutzer darf sich mit Zeigern rumschlagen, was entweder weniger Sicherheit (rohe Zeiger) oder mehr Tipparbeit bedeutet (Smart-Pointer).Wenn es wirklich nur darum geht, die Implementierung zu verstecken, greife ich immer zum pimpl-Idiom. Solange die Klasse nicht von *außen* erweitert werden muss, kann Implementation ja immer noch polymorph sein.
-
Die erste Variante entspricht in etwa dem Prinzip vom Microsoft COM-Modell. Trotz .NET immer noch das gebräuclichste Verfahren für Komponenten-Entwicklung unter Windows.
-
Helper schrieb:
Die erste Variante entspricht in etwa dem Prinzip vom Microsoft COM-Modell. Trotz .NET immer noch das gebräuclichste Verfahren für Komponenten-Entwicklung unter Windows.
natürlich nur, dass das Interface nicht von IUNKNOWN abgeleitet ist, es desweiteren kein release/addref/query_interface gibt,und der gesamte Unterbau der Com fehlt.
aber rein äußerlich ist es natürlich verwandt :p .@operator void aber bitte dann immer mit templates, so is der ganze schrott ja statisch ;),andererseits haste den pointer ja eigentlich bei deiner Klasse nur unsichtbar gemacht, intern musst du dich immernoch mit dem ganzen Kram rumschlagen. Das andere system versucht halt nur nicht zu verheimlichen, dass es eigentlich nur auf alles und jeden pointed :p.
Der größte nachteil an dem 2. system ist aber, dass man, wenn man das ganze wirklich dynamisch machen will,die Verwaltete Klasse dazu zwingen muss, einen default ctor zu haben,und das ist nicht wirklich das ware.
-
operator void schrieb:
Solange die Klasse nicht von *außen* erweitert werden muss, kann Implementation ja immer noch polymorph sein.
Du meinst mit einem Zeiger zur Basisklasse der Implementation(en) im Interface?
otze schrieb:
Der größte nachteil an dem 2. system ist aber, dass man, wenn man das ganze wirklich dynamisch machen will,die Verwaltete Klasse dazu zwingen muss, einen default ctor zu haben,und das ist nicht wirklich das ware.
Warum denn das? Kannst du das mal genauer erklären?
-
Ich verwende da gerne das pimpl Idiom. Das kann man dann schön auf 0 mehrkosten bringen (kostet dafür etwas lesbarkeit)
//Class.hpp #ifndef CLASS_HPP_INCLUDED #define CLASS_HPP_INCLUDED #ifdef OPTIMIZING #include "ClassImpl.hpp" typedef ClassImpl Class; #else class ClassImpl; class Class { private: ClassImpl* impl; public: //achtung: CopyCtor und op= fehlen noch Class(); ~Class(); void foo(); }; #endif //Class.cpp #ifndef OPTIMIZING #include "Class.hpp" #include "ClassImpl.hpp" Class::Class() : impl(new ClassImpl()) {} Class::~Class() { delete impl; } void foo() { impl->foo(); } #endif //ClassImpl.hpp und ClassImpl.cpp sind //dann die normalen implementationen
In der release Version definiert man dann OPTIMIZING und schon wird das pimpl Idiom aufgelöst.
Denn bei der Release Version kann mir die Dauer des Kompilierens ja relativ egal sein.