Eine Frage zu Funktionszeigern
-
Hi,
ich such schon ne weile nach einer Lösung für ein Problem, aber so richtig geht das nicht nicht.Hab mal folgenden Vorschlag gefunden:
http://www.newty.de/fpt/functor.htmlDaran "passt" mir aber nicht, dass ich sowohl das Objekt als auch den Zeiger auf die Funktion übergeben muss.
Rein theoretisch steht die Adresse der Funktion, für das Objekt, ja irgendwo im Speicher und der PC wird beim aufrufen der Funktion damit geladen.Alles was ich tun möchte ist die Adresse auf eine möglichst einfache Art zu speichern und dann die Funktion aufzurufen.
Gibt es da eine einfachere Lösung?
Wegen mir auch C
Meine TFunktor sieht so aus:
class TFunctor { public: virtual void operator()(MSTEvent* event)=0; virtual void Call(MSTEvent* event)=0; };und ich möchte beispielsweise einen Zeiger auf folgende Funktion:
void EventHandler::eventRegisterEvent(MSTEvent * event)aufrufen.
Also:myCallback->callback(event);und unter callback wird jetzt die
eventRegisterEventaufgerufen.
Gruß oli
-
Du mußt unterscheiden zwischen Funktionszeigern und Methodenzeigern (d.h. Klassenfunktionen).
Ein Funktionszeiger (und auch eine statische Klassenmethode) benötigen nur eine Adresse, aber ein Methodenzeiger besteht intern aus einem variablen Objekt und einem Offset auf die Klassenmethode, d.h. du mußt dann die konkrete Klasse angeben:
typedef void (A::*Func)(int); // Func ist nun ein Zeiger auf eine Klassenfunktion (aber nur der Klasse A) Func f = &A::myFunc; // Zuweisung an void A::myFunc(int)
-
Hi,
danke für die Antwort. Hab schon fast erwartet, dass das so ist
Aber dann halt auf diese Art. Jetzt noch ne Frage zu vererbten Klassen.
Ich hab folgendes:
class KlasseA { ..... } class KlasseB : public KlasseA { public: ..... eventRegisterEvent(MSTEvent * event); }Wie übergebe ich jetzt den Methodenzeiger?
KlasseB objB; TSpecificFunctor<KlasseB> myCallback(&objB, &KlasseB::eventRegisterEvent);Funktioniert irgendwie nicht.
Gruß Oli
-
"Funktioniert irgendwie nicht" als Fehlermeldung funktioniert in diesem Forum leider nicht. Die hier oft zitierte Glaskugel ist leider zu ungenau um die Fehlermeldung zu sehn die du auf dem Schirm hast, genausowenig sehen wir die Definition von TSpecificFunctor. Nur wenn du uns aufklaerst wie das denn funktionieren soll, koennen wir dir eventuell helfen und sagen was schief geht.
Bis dahin heisst es:
"Wenn dus sagst. Dann funktionierts eben so nicht."
-
pumuckl schrieb:
"Funktioniert irgendwie nicht" als Fehlermeldung funktioniert in diesem Forum leider nicht. Die hier oft zitierte Glaskugel ist leider zu ungenau um die Fehlermeldung zu sehn die du auf dem Schirm hast, genausowenig sehen wir die Definition von TSpecificFunctor. Nur wenn du uns aufklaerst wie das denn funktionieren soll, koennen wir dir eventuell helfen und sagen was schief geht.
Ja sorry, hab ich gar nicht dran gedacht
. für mich wars klar 
Also dann mal alles:
- Fehlermeldung
no matching function for call to ‘TSpecificFunctor<EventHandler>::TSpecificFunctor(EventHandler* const, void (EventHandler::)(MSTEvent))’
- Die stelle wo es schief geht:
TSpecificFunctor<EventHandler> myCallback(this, EventHandler::eventRegisterEvent);- Die Klasse TSpecificFunctor
class TFunctor { public: virtual void operator()(MSTEvent* event)=0; virtual void Call(MSTEvent* event)=0; }; template <class TClass> class TSpecificFunctor : public TFunctor { private: void (*fpt)(MSTEvent*); const TClass* pt2Object; public: TSpecificFunctor(const TClass* _pt2Object, void (*_fpt)(MSTEvent*)) { fpt=_fpt; pt2Object = _pt2Object; }; // override operator "()" void operator()(MSTEvent* event) { (*pt2Object.*fpt)(event);}; // execute member function // override function "Call" void Call(MSTEvent* event) { (*pt2Object.*fpt)(event);}; };Thx
Gruß Oli
-
sambalmueslie schrieb:
no matching function for call to ‘TSpecificFunctor<EventHandler>::TSpecificFunctor(EventHandler* const, void (EventHandler::)(MSTEvent))’
TSpecificFunctor(const TClass* _pt2Object, void (*_fpt)(MSTEvent*))Der Konstruktor erwartet als zweites Argument einen Zeiger auf eine freie Funktion, die einen pointer auf MSTEvent als Parameter hat und keinen Rueckgabewert. Du hingegen uebergibst ihr einen Pointer auf eine Memberfunktion, was zwei verschiedene Paar Schuhe (zwei unterschiedliche Typen) sind.
-
pumuckl schrieb:
Der Konstruktor erwartet als zweites Argument einen Zeiger auf eine freie Funktion, die einen pointer auf MSTEvent als Parameter hat und keinen Rueckgabewert. Du hingegen uebergibst ihr einen Pointer auf eine Memberfunktion, was zwei verschiedene Paar Schuhe (zwei unterschiedliche Typen) sind.
Ah oki, thx. Ich habs hab da was beim Copy-Paste und ausprobieren verschluckt.
So funktioniert es jetzt :TSpecificFunctor(TClass* _pt2Object, void (TClass::*_fpt)(MSTEvent*))Danke
Gruß Oli
-
gleich nochwas, bevor du es dir angewoehnst: Namen mit fuehrendem Unterstrich sind zum Teil fuer den Compiler reserviert. Gibt da meines Wissens ne liste, aber am Besten umgeht man Probleme damit, indem man Namen mit fuehrendem unterstrich einfach vermeidet. Ich persoenlich mach in solchen Faellen den unterstrich hinten ran

-
pumuckl schrieb:
gleich nochwas, bevor du es dir angewoehnst: Namen mit fuehrendem Unterstrich sind zum Teil fuer den Compiler reserviert. Gibt da meines Wissens ne liste, aber am Besten umgeht man Probleme damit, indem man Namen mit fuehrendem unterstrich einfach vermeidet. Ich persoenlich mach in solchen Faellen den unterstrich hinten ran

Hm danke für den Tipp, die unterstriche waren schon vorgegeben, ich nenn die Variablen immer gleich und verwendet den this-Zeiger um zu unterscheiden.
Gruß Oli
-
Mal nen Beispiel zu Funktionszeigern, das dir das nen bissel erklären sollte:
template<typename object, typename result, typename param1> struct mem_fn_call { typedef result (object::*fnPtr)(param1 const&); mem_fn_call(object const& inst, fnPtr func) : inst(inst), func(func) {} result operator()(param1 const& param) { return (inst.*func)(param); } private: object const& inst; fnPtr func; };class foo { public: void bar(std::size_t i) { std::cout << i << std::endl; } }; int main() { foo inst; mem_fn_call<foo, void, std::size_t>(inst, &inst::bar)(10); }
-
Thx,
ja so langsam lichtet sich der Nebel etwas
Was muss ich eigentlich tun, wenn ich die Adresse auf die der Funktionszeiger zeigt ausgeben möchte(muss) ???
Hab mal folgendes versucht:
void (FileHandler::*fpt)(MSTEvent*); fpt = &FileHandler::callbackOpenFilestream; std::cout << "FileHandler::initHandler::fpt:" << std::hex << (fpt) << std::endl;Dann bekomme ich aber als ausgabe nur eine "1".
Bei
std::cout << "FileHandler::initHandler::fpt:" << std::hex << (&fpt) << std::endl;bekomme ich:
FileHandler::initHandler::fpt:0xbfd5afbc
aber das dürfte ja die Adresse des Zeigers sein und nicht der Funktion.
Hintergrund ist, dass ich "irgendwo" ein "Segmentation Fault" bekomme. Jetzt wollte ich mal überprüfen, dass die Funktion auf die gezeigt wird auch die richtige ist und sich das nirgends ändert.
Habs auch mal bisschen mit dem "gdb" versucht, bin aber da auch noch nicht sonderlich weit gekommen.Gruß Oli
-
Debug einfach mal ... also so wie ich es da aufgeschrieben hab ist es korrekt(sollte) ... ehm evtl. einfach mal durch Steppen ...
-
Was muss ich eigentlich tun, wenn ich die Adresse auf die der Funktionszeiger zeigt ausgeben möchte(muss) ???
Wie ich schon geschrieben habe, besteht ein Methodenzeiger nur aus einem Offset (d.h. die 1 kann schon stimmen).
Die wirkliche Adresse wird dann erst beim Aufruf ermittelt (und an diese kommst du nicht dran, besonders bei virtuellen Funktionen und Mehrfachvererbung wird es ziemlich komliziert -)Nachtrag:
Wenn du ein konkretes Objekt hast, dann kannst du natürlich die Adresse bestimmen:&(obj.fpt) &(obj->*fpt)
-
(D)Evil schrieb:
Debug einfach mal ... also so wie ich es da aufgeschrieben hab ist es korrekt(sollte) ... ehm evtl. einfach mal durch Steppen ...
Debuggen tu ich fleißig
..
meinte das nicht auf deinen Teil bezogen.
Gruß Oli
-
Th schrieb:
Nachtrag:
Wenn du ein konkretes Objekt hast, dann kannst du natürlich die Adresse bestimmen:&(obj.fpt) &(obj->*fpt)Jo genau sowas hab ich gesucht. Bin irgendwie aber nicht draufgekommen.
..
Gruß Oli