Zeiger auf Klassenfunktionen



  • Hallo,

    ich habe :

    class A
    { public:
        int f(int a, int b);
    };
    

    Nun will ich einen Zeiger auf diese Funktion als Eigenschaft an eine andere Klasse übergeben. Also schreibe ich:

    class B
    { public:
         int (A::*func)(int, int);
    };
    

    Soweit, so gut.
    Wenn ich jetzt aber die Funktion f ändern will in

    int f(int a, int b=0);
    

    (man beachte das int b=0)
    ... wie muß jetzt der Zeiger aussehen?

    int (A::*func)(int, int=0);
    

    geht nicht.

    Vielen Dank für eure Hilfe.



  • ... wie muß jetzt der Zeiger aussehen?

    So wie vorher. Das Hinzufügen eines Default-Parameters ändert den Typ der Funktion nicht. Er ist danach immer noch:

    int (A::*func)(int, int);
    

    Und wenn du die Funktion indirekt über den Funktionszeiger aufrufen willst, musst du auch weiterhin zwei Parameter angeben.



  • Ich will ja aber den zweiten Parameter nicht angeben müssen, darum mach ich ja die Initialisierung int b=0.

    Geht das denn nicht?



  • nein, denn default parameter werden waehrend der compile time ausgewertet.

    funktionspointer aber logischerweise erst zur runtime.



  • Geht das denn nicht?

    Nein. Das einfachste wäre, wenn du statt eines Def-Parameters einfach Überladung einsetzen würdest.

    Alternativ könnten dir binder helfen. Hier mal am Beispiel boost::function + boost::bind.

    #include <boost/bind.hpp>
    #include <boost/function.hpp>
    #include <iostream>
    class A
    {
    public:
    	void func(int i, int j= 0)
    	{
    		std::cout << i << " " << j << std::endl;
    	}
    };
    
    class B 
    {
    public:
    	B(void (A::*func)(int, int), A* p) 
    		: func_(boost::bind(func, p, _1, 0))
    	{}
    	void call()
    	{
    		func_(17);
    	}
    private:
    	boost::function1<void, int> func_;
    };
    
    int main()
    {
    	A a;
    	B b(&A::func, &a);
    	b.call();
    }
    

    Das entspricht aber natürlich nicht mehr einem Defaultparameter.

    Alternativ geht natürlich auch sowas:

    template <class R, class T, class A, class A2>
    struct MemFun2Def2
    {
    public:
    	MemFun2Def2(R(T::*fun)(A, A2), A2 a2)
    		: fun_(fun)
    		, a2_(a2)
    	{}
    	R operator()(T* o, A a1)
    	{
    		return (o->*fun_)(a1, a2_);
    	}
    	R operator()(T* o, A a1, A2 a2)
    	{
    		return (o->*fun_)(a1, a2);
    	}
    private:
    	R(T::*fun_)(A, A2);
    	A2 a2_;
    };
    class A
    {
    public:
    	int func(int i, int j= 0)
    	{
    		std::cout << i << " " << j << std::endl;
    		return 0;
    	}
    };
    
    class B 
    {
    public:
    	B(int (A::*func)(int, int)) 
    		: func_(func, 0)
    	{}
    	void call()
    	{
    		A a;
    		func_(&a, 17);
    		func_(&a, 17, 23);
    	}
    private:
    	MemFun2Def2<int, A, int, int> func_;
    };
    
    int main()
    {
    	B b(&A::func);
    	b.call();
    }
    

    Naja, aber ich denke Überladung wäre hier wirklich das beste.



  • hallo,
    boost::bind is nicht anders als ne klasse die function, memberfunction pointer usw verwaltet...ist ein allgemeinerer Ersatz für Funktionszeiger?

    auf deren homepage steht:
    boost::bind is a generalization of the standard functions std::bind1st and std::bind2nd. It supports arbitrary function objects, functions, function pointers, and member function pointers, and is able to bind any argument to a specific value or route input arguments into arbitrary positions. bind does not place any requirements on the function object; in particular, it does not need the result_type, first_argument_type and second_argument_type standard typedefs.

    was sind arbitrary function objects, das wort höre ich zum ersten mal;-)?

    thx



  • funktionsobjekte, die einen Parameter haben.



  • was zählt bei dir alles als funltionsobjekt? meinst du diesen _1 param?

    cu


Anmelden zum Antworten