Problem mit CObArray und abgeleiten Klassen *HELP*
-
hab ich ja. also B ist meine Eigene.
class B : public CWnd { public: B(); virtual ~B(); void SetTestName(CString name){m_TestName = name;}; };
von B geerbte:
class C: public B { public: C(); virtual ~C(); int Hallo(void){return 9;}; };
ebenfalls von B geerbte Klasse:
class D: public B { public: D(); virtual ~D(); int Servus(void){return 1;}; };
soweit so gut. Jetzt will ich C und D in ein CObArray ablegen um dann später bei bedarf darauf zugreifen zu können.
CObArray oba; oba.Add( new C() ); oba.Add( new D() ); // Ich will auf die Elemente des Arrays zugreifen und von dessen Funktionen // gebrauch machen oba.GetAt(0)->Hallo(); // Hätte ich gern, geht aber nicht oba.GetAt(1)->Servus(); // Hätte ich gern, geht aber nicht oba.GetAt(0)->SetTestName("blabla"); // Nicht mal das funzt
stattdessen leifert mir: oba.GetAt(0)->(nur die CObject Funktionen)
Was ist mein Problem?
-
Nur SetTestName sollte gehen. Du kannst nur die Funktionen Aufrufen die auch in Klasse B sind.
-
Ach ist klar das das nicht geht. GetAt gibt ja nur CObject Zeiger zurück und nicht Zeiger auf die Basisklasse. Ich an deiner Stelle würde lieber std::vector aus der C++ STL nehmen. Dann hast du das Problem nicht. Oder du castest auf die Basisklasse:
class B : public CWnd { public: virtual ~B() { } void SetTestName(CString name){}; }; class C: public B { }; class D: public B { }; CObArray oba; oba.Add( new C() ); oba.Add( new D() ); static_cast<B*>(oba.GetAt(0))->SetTestName("blabla");
Sowas ist aber absolut scheisse.
-
hmm, ok ich seh das Problem liegt darin das ich gerne verschiedene Typen in einem Array hätte. Das geht aber nicht weil sowohl CObArray als auch vector nur eine Pointerliste führen.
Ich hab auch schon rumprobiert meine Klassen C und D durch eine Template Klasse trotzdem im vector abzulegen. Geht natürlich auch nicht, da der vector nen realen Typ brauchtGibt es dennoch eine Möglichkeit für mein Vorhaben? Evt. ne fertige Klasse oder so? Das Problem ist, ich weis nicht genau nach was ich z.B. bei CodeGuru suchen soll?
-
std::vector<Basisklasse*> geht doch.
-
ja schon, aber das bringt mir nix. Ich kann dann nur auf die Funktionen der Basisklasse zugreifen, nicht auf die Funktionen die zusätzlich in der Geerbten Klassen zur Verfügung stehen.
vector<B*> vec; C c; vec.pushback(&c); vec[0]->SetTestName("hi"); // geht vec[0]->Hallo() // geht nicht
Meine Idee ist, auch wenn etwas unüblich, das ich einem Array die ganzen Typen von den Derivaten einer Basisklasse ablegen kann. Da sie sich vom Inhalt der bereitgestellten Funktionen unterscheiden.
Am folgendem Beispiel zeige ich wie es aussehen sollte:
class External_Device : public CObject { public: External_Device(CString adress, CString name, CString signal, int systemnr); ~External_Device(void); bool InitDevice(void){return true;}; // Set Device into the init state bool SetOutputOn(int outputnumber){return true;}; // Set Output On bool SetOutputOff(int outputnumber){return true;}; // Set Output Off bool SetInputOn(int inputnumber){return true;}; // Set Input On bool SetInputOff(int inputnumber){return true;}; // Set Input Off bool SuspendDevice(void){return true;}; // Pauses the device bool WakeupDevice(void){return true;}; // Wakes up the device private: typedef struct{ int systemnr; // Systemnumber CString signal; // Kind of signal CString adress; // Adress on the IEEE or Serial bus CString name; // Devicename (optional) }DEVICESTRUCT; DEVICESTRUCT devstruct; }; class Device_33120A : public External_Device { public: Device_33120A(CString adress,CString name,CString signal,int systemnr); virtual ~Device_33120A(void); SetCurrent(float cur); }; class Device_CMU200 : public External_Device { public: Device_CMU200(CString adress,CString name,CString signal,int systemnr); virtual ~Device_CMU200(void); SetTriangle(float freq); };
Nun möchte ich die Standard-Funktionen aus der Basisklasse wie z.B. InitDevice auf alle ca. 15 Devices anwenden. Denn Diese hängen am GBIP-Bus (IEEE488).
for(int i=0; i<vec.size();i++){ vec.[i]->InitDevice(); }
Für Gerätespezifische Funktionen:
vec[0]->SetCurrent(2,88); vec[1]->SetTrianlge(850);
Ist vielleicht etwas ungewöhnlich, da man normalerweise in einem solchen Fall eher lauter Klassen variablen erzeugt. Nur werde ich dann 15 varibalen haben und 15 mal InitDevice() machen müssen. Das möchte ich umgehen.
-
Ich kann dann nur auf die Funktionen der Basisklasse zugreifen, nicht auf die Funktionen die zusätzlich in der Geerbten Klassen zur Verfügung stehen.
Irgendwas stimmt mit deinem Design nicht. Das ist doch Schwachsinn was du da vorhast.
-
naja irgentwo ist das schon Blödsinn, aber in meinem Fall macht es sogar Sinn
-
Du solltest deine Frage nochmal im C++ Unterforum stellen. Hier im MFC Forum wirst du wohl kaum Hilfe bekommen.
-
Schau dir mal virtual an...
Du kannst nun mal nur Funktionen aufrufen, die auch
in der Basisklasse definiert sind. Anders gehts
nicht, sonst must du den Zeiger jeweils casten.Devil
-
Hab jetzt ne mehr oder weniger gute Lösung für mein Prob:
vector<External_Device*> vec; vec.push_back(new Device_33120A()); vec.push_back(new Device_CMU200()); u.s.w. for(...){ vec[i]->InitDevice(); // In Basisklasse definierte Funktionen vec[i]->SetOutputOn(0); } // Um nun von den Funktionen gebrauch zu machen die in // den Vererbten Klassen definiert sind muss ich casten Device_33120A *dev= new Device_33120A(); dev = (Device_33120A*)vec[0]; dev->SetCurrent(2,88); vec[0] = dev; delete dev; Device_CMU200 *dev = new Device_CMU200(); dev = (Device_CMU200*)vec[1]; dev->SetTriangle(850); vec[1] = dev; delete dev;
oder der andere Ansatz mit virtual (thnx devil
):
class External_Device : public CObject { public: External_Device(CString adress, CString name, CString signal, int systemnr); ~External_Device(void); bool InitDevice(void){return true;}; // Set Device into the init state bool SetOutputOn(int outputnumber){return true;}; // Set Output On ... virtual SetCurrent(); virtual SetTriangle(); ... };
hier sammle ich zunächst alle spezifischen Funktionen aus den Derivaten in der Basisklasse als (virtual) zusammen, so müssen dann später die Vererbten Klassen jeweils ihre Funktionen implementieren und gut ist. Kein casten mehr nötig. Ist wohl die bequemere Lösung.