Funktionskörper für abstrakte Funktion in Basisklasse
-
Eigentlich finde ich es nicht logisch, c kriegt zweimal von a eine abstrakte Funktion und b::x sollte dann doch a::x halt zweimal überschreiben.
Das c direkt von a erbt, war zur vereinfachung, in meiner Anwendung, gibt esungefähr so, nuoch eine Klasse a2:class a{ public: virtual void x()=0; }; //class a: public a{ [edit:] class a2: public a{ public: virtual void y()=0; }; class b:public a{ public: virtual void x(); }; void b::x(){ } class c:public b, public a2{ public: virtual void y(); }; void c::x(){ }
Das sollen später mal Klassen für ein GUI werden.
Es gibt abstrakte Klassen Component, Control, Button, ..., die jeweils von einander abgeleitet werden, und die dazu gehörigen Funktionskörper sind in Extraklassen. ImpComponent , ImpControl...
ImpButton sollte dann von Button und ImpControl abgeleitet werden.Die "Imp"-Klassen sind dann in einer DLL und das Hauptprogramm kennt nur die abstrakten Klassen.
Zum btw:
Mit virtual find ich es eigentlich klarer.
-
Ne, es is eben nicht logisch.
Dein c erbt von a und von b (somit noch einmal von a), hat also somit 2mal von
a geerbt. Einmal wird die pure virtual Funktion auch überschrieben, nur eben
das zweite Mal nicht.Mit virtuellen Basisklassen klappts, wobei ich mir vllt trotzdem irgendwie
das Design nochmal durchdenken würde.class Base { public: virtual void mf() = 0; }; class Derived : virtual public Base { public: virtual void mf(); }; class MoreDerived : virtual public Base, public Derived { };
-
class a{ public: virtual void x()=0; }; class a: public a{ public: virtual void y()=0; };
interessant...
-
Oh, da sollte a2 hin
Danke, das klappt.
Aber warum kann man keinen static_cast von einer Basisklasse zu C machen, aber einen dynamic_cast?
-
static_cast geht, nur kratzt dir das prorgamm ab,wenn die basisklasse nicht wirklich c ist.
-
Wie geht denn das beim static_cast, das funktioniert nämlich nicht:
c dd; a* d2=ⅆ c* d3; d3=dynamic_cast<c*>(d2); // ok d3=static_cast<c*>(d2); // Compilerfehler: invalid static_cast from type `a*' to type d3=(c*)(d2); // Compilerfehler: cannot convert from base `a' to derived type `c' via virtual base `c*'
@Tankian: Was sollte icb den beim Klassendesign verändern?
-
@Tankian: Was sollte icb den beim Klassendesign verändern?
Mehrfachvererbung vermeiden ..
Zum Beispiel könntest du deine gesamten Impl-Klassen
mit Layering implementieren.class ImplButton : public ImplControl { public: ImplButton() { } virtual void onClick() { // ... } }; class Button : public Control { public: Button() : impl(new ImplButton) { // normalerweise würd ich sowas mit auto_ptr machen .. } ~Button() { delete impl; } virtual void onClick() { impl->onClick(); } private: ImplButton* impl; };
In dem Beispiel hier is es grad auch dasselbe wie das pimpl-Idiom.
Tankian
-
BeniBela schrieb:
Zum btw:
Mit virtual find ich es eigentlich klarer.War auch nur ein Vorschlag, ist ja schliesslich nicht falsch, es nochmals hinzuschreiben.
BeniBela schrieb:
d3=dynamic_cast<c*>(d2); // ok d3=static_cast<c*>(d2); // Compilerfehler: invalid static_cast from type `a*' to type
Also bei mir funktioniert static_cast problemlos. Probier das mal mit einem Minimalbeispiel. Wenn's dann funktioniert, muss das Problem woanders liegen.
Übrigens, welchen Compiler hast du?@Tankian
Events so zu handeln find ich recht unpraktisch. Funktionsadapter scheinen mir da passender zu sein. Wenn ich das richtig sehe, musst du für alle Controls eine eigene Klassenimplementation schreiben oder seh ich das falsch.
Da ich momentan für einen Optionsdialog eines Plugins an einem kleinen GUI arbeite, welches die WinAPI kapselt, hab ich mir darüber auch schon einige Gedanken gemacht. Und da finde ich die Vorgehensweise, wie es zB auch bei C++/CLI gemacht wird, praktischer.
-
Bei einem Minimalprogramm kommt das gleiche :(:
#include <iostream> class a{ public: virtual void x()=0; }; class b:virtual public a{ public: virtual void x(); }; void b::x(){std::cout << "b::x";} class c: virtual public a ,public b { public: }; int main(int argc, char *argv[]) { c dd; a* d2=ⅆ c* d3; d3=dynamic_cast<c*>(d2); d3->x(); //wenn die statischen weggelassen werden, wird b::x aufgerufen. d3=(c*)(d2); d3=static_cast<c*>(d2); system("PAUSE"); return 0; }
make.exe -f "E:\temp\delete\temp\Makefile.win" all g++.exe -c main.cpp -o main.o -I"D:/MinGW/include" -I"D:/MinGW/include/c++" -I"D:/MinGW/include/sys" -I"D:/MinGW/include/c++/3.2.3" -I"D:/MinGW/include/c++/3.2.3/mingw32" -I"E:/c++komps/simpleUtils" -I"D:/MinGW/include/dx" -I"D:/ddks/Microsoft Platform SDK/Include" -fexpensive-optimizations main.cpp: In function `int main(int, char**)': main.cpp:24: cannot convert from base `a' to derived type `c' via virtual base `a' main.cpp:25: invalid static_cast from type `a*' to type `c*' make.exe: *** [main.o] Error 1
Der Coompiler ist MingW mit Gcc 3.2.3.
zum Design:
@Tankian:
Dann muss aber Button die Klasse ImplButton kennen, das wollte ich gerade vermeiden.
@groovemaster:
Was hat denn C++/CLI mit GUI zu tun? Ist das nicht der Nachfolger von Managed C++?
-
groovemaster:
Natürlich würd ich das mit den Events selbst auch nicht so lösen, ich hab nur
blind drauf los irgendeinen Methodennamen gewählt, der halbwegs zu Control passt.
Normalerweise würd ich da mit boost::signal arbeiten.BeniBela:
Google mal selbst nach dem pimpl-Idiom.
Mein Beispiel sollte nur Layering zeigen, den
Rest darfst dir selbst ergooglen.Tankian
-
@BeniBela
Ich vermute mal, dass die virtuelle Vererbung deinen Compiler streiken lässt. Da das keine einfache Thematik ist, solltest du dir mal anschauen, was der Standard dazu sagt. Vielleicht ist aber auch Hume so gnädig und klärt dich (uns) auf. Wobei ich mir momentan nicht sicher bin, warum und ob überhaupt virtuelle Vererbung bei dir notwendig ist.
BeniBela schrieb:
Was hat denn C++/CLI mit GUI zu tun?
C++/CLI ist die MS Antwort für das Designen von GUIs (Forms) unter C++. Zumindest in der aktuellen Ausgabe des Visual Studios. Wie du schon richtig gesagt hast, war Managed C++ mehr oder weniger der Vorgänger.
-
Na super, der Standard verbietet es
Dann werd ich es wohl mal mit dem Pimpl-Idiom versuchen, und mir C++/CLI angesehen.Danke für die Antworten.