Leana Geschrieben 28. Mai 2003 Geschrieben 28. Mai 2003 hallo ich habe eine methode in meiner datenhaltungsklasse, die den paramter einer callbackfunktion bekommen soll. in meiner anderen klasse, die diese methode aufrufen soll erstell ich den funktionspointer //funktionspointer erstellen void (CErweiterungSnapShotDlg::*pfunction)(CString strProzess, CString strWert); // jetzt zeigt pfunction auf CallbackFunction pfunction = &CErweiterungSnapShotDlg::CallbackFunction; nun will ich die methode der datenhaltungsklasse aufrufen und den funktionspointer übergeben mein problem ist, welchen datentyp muss ich denn in die methode reinschreiben für den funktionspointer, es soll allgemein gehalten werden... also egal in welcher klasse diese methode aufgerufen wird, es kann immer ein beliebiger funktionspointer mitgegeben werden.... bitte, kann mir jemand helfen? Zitieren
Klotzkopp Geschrieben 28. Mai 2003 Geschrieben 28. Mai 2003 Original geschrieben von Leana mein problem ist, welchen datentyp muss ich denn in die methode reinschreiben für den funktionspointer, es soll allgemein gehalten werden...Der Typ des Zeigers pfunction ist void(CErweiterungsSnapShotDlg::*)(CString,CString) also egal in welcher klasse diese methode aufgerufen wird, es kann immer ein beliebiger funktionspointer mitgegeben werden....Falls du mit "beliebig" Zeiger auf Funktionen anderer Klassen oder mit anderer Signatur meinst: Das geht nicht. Du kannst an eine solche Funktion nur Zeiger auf Memberfunktionen von CErweiterungsSnapShotDlg übergeben, die void zurückgeben und zwei CString-Parameter haben. Du kannst eine solche Funktion über den Zeiger auch nur aufrufen, wenn du eine Instanz von CErweiterungsSnapShotDlg hast. Zitieren
Leana Geschrieben 28. Mai 2003 Autor Geschrieben 28. Mai 2003 das muss schon irgendwie gehen, aber wie? templates vielleicht! kann mir jemand helfen! schließlich sollen ja die schnittstellen allgemein gehalten werden und nicht nur von diesem einem dialog Zitieren
Klotzkopp Geschrieben 28. Mai 2003 Geschrieben 28. Mai 2003 Du könntest etwas in der Art machen: class Test { public: template <typename returntype, class C, typename Param1, typename Param2> void foo( returntype(C::*funcp)(Param1,Param2) ) { C x; Param1 p1; Param2 p2; (x.*funcp)( p1, p2 ); } }; class Callee { public: void bar( int x, double y ) { // irgendwas } }; int main() { Test t; t.foo( &Callee::bar ); }[/CODE] Zitieren
Leana Geschrieben 28. Mai 2003 Autor Geschrieben 28. Mai 2003 ja, genau, dass sieht schon viel besser aus! danke kannst du mir nur kurz erleutern, da wo du Param 1 und param 1 hast kann ich ja auch z.b. CString oder int oder so reinschreiben oder, wenn das fest definiert sein soll? Zitieren
Klotzkopp Geschrieben 28. Mai 2003 Geschrieben 28. Mai 2003 Alles, was nicht variabel ist, kannst du aus der Templatedeklaration rausnehmen und fest in den Funktionskopf reinschreiben: template <class C> void foo( void(C::*funcp)(CString,int) )[/CODE]Hier sind Rückgabetyp und Argumenttypen festgelegt, nur die Klasse nicht. Zitieren
Leana Geschrieben 28. Mai 2003 Autor Geschrieben 28. Mai 2003 ok ich hab das jetzt umgesetzt, mal schauen ob es geht. kannst du mir aber bitte erklären warum ich fehler bekomme, wenn es outline ist? und es bei inline das übersetzen funktioniert Zitieren
Leana Geschrieben 28. Mai 2003 Autor Geschrieben 28. Mai 2003 jetzt bekomm ich ständig linkerfehler keine ahnung was falsch ist kannst du nochmal drüber gucken in der klasse steht //öffentliche methoden public: template <typename returntype, class C> void GetActualProcInformation(CString strProzess, int iInfoArt, returntype(C::*funcp)(CString,CString) ) { C x; int iStelle = FindPlace(strProzess); CString strBack; switch(iInfoArt) { case CPU_AUSLASTUNG: strBack = m_ProzessArray[iStelle].GetWert(); break; case VERGANGENE_ZEIT: strBack = m_ProzessArray[iStelle].GetTime(); break; case HANDLE_PROZESS: strBack = m_ProzessArray[iStelle].GetHandleCount(); break; case P_ID: strBack = m_ProzessArray[iStelle].GetProzessID(); break; case THREAD_HANDLE: HANDLE = m_ProzessArray[iStelle].GetThreadHandle(); //strBack break; default: break; } x.*funcp (strProzess, strBack); } mein aufruf in der anderen klasse: //funktionspointer erstellen void (CErweiterungSnapShotDlg::*pfunction)(CString strProzess, CString strWert); // jetzt zeigt pfunction auf CallbackFunction pfunction = &CErweiterungSnapShotDlg::CallbackFunction; CString strProc = m_ListProzesse.GetItemText(0,0); m_System.GetActualProcInformation(strProc, 1, pfunction); wo liegt der fehler Zitieren
Klotzkopp Geschrieben 28. Mai 2003 Geschrieben 28. Mai 2003 Original geschrieben von Leana wo liegt der fehler Wie lautet denn die Fehlermeldung? Nachtrag: Ich kann's mir denken... Die Definition der Templatefunktion muss in jeder Übersetzungseinheit, die sie verwendet, zur Verfügung stehen. Da einige Compiler mit dem Schlüsselwort export bei Templates nicht zurechtkommen, ist es am einfachsten, wenn du die Funktionsdefinition in die Headerdatei setzt. Zitieren
Klotzkopp Geschrieben 28. Mai 2003 Geschrieben 28. Mai 2003 Original geschrieben von Leana er kann nicht linken Das hat schon seinen Grund, wenn ich nach dem genauen Wortlaut der Fehlermeldung frage, weil die Hinweise für die Fehlerursache liefern kann. Oder lautet die Meldung wirklich genau so? Kann ich mir nicht vorstellen. Zitieren
Leana Geschrieben 28. Mai 2003 Autor Geschrieben 28. Mai 2003 jetzt hab ich es doch geschafft das er sich übersetzen wollte... also ich guck mal ob es geht, ich versteh diesen compiler echt net kannst mir das mit dem outline, inline erklären Zitieren
Leana Geschrieben 28. Mai 2003 Autor Geschrieben 28. Mai 2003 och mann ich dreh gleich durch.... bei dem gibt es ne fehlermeldung x.*funcp(strProzess, strBack); fehlermeldung: rror C2064: term does not evaluate to a function d:\steffi\systemabfragentest\erweiterungsnapshot\erweiterungsnapshotdlg.cpp(1161) : see reference to function template instantiation 'void __thiscall CSystemInfo::GetActualProcInformation(class CString,int,void (__thiscall CErweiterungSnapSh otDlg::*)(class CString,class CString))' being compiled Zitieren
Leana Geschrieben 28. Mai 2003 Autor Geschrieben 28. Mai 2003 ich hab nur die klammern um x.*fppointer vergessen, danke dir super hilfe... wenn du aber bitte trotzdem noch erklären könntest, warum das inline stehen muss Zitieren
Klotzkopp Geschrieben 28. Mai 2003 Geschrieben 28. Mai 2003 Aus einer Templatedefinition wird zunächst einmal kein Code erstellt. Der Code wird erst dann produziert, wenn das Template benutzt wird, und zwar für jeden Templateargument-Typ (bzw. für jede Kombination von Typen bei mehreren Templateargumenten) einmal. Das hat aber zur Folge, dass die Definition in jeder Übersetzungseinheit verfügbar sein muss, in der sie verwendet wird. In C++ ist dafür das Schlüsselwort export vorgesehen, das aber viele Compiler nicht unterstützen. Daher setzt man die Templatedefinitionen einfach in die Header. Wenn eine cpp-Datei das Template nicht braucht, passiert nichts (siehe oben), und wenn doch, ist der Code da. Das ist auch der Grund, warum die Container der Standardbibliothek (vector, map usw.) in den jeweiligen Headerdateien implementiert sind. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.