Chinaunix首页 | 论坛 | 博客
  • 博客访问: 180252
  • 博文数量: 36
  • 博客积分: 2510
  • 博客等级: 少校
  • 技术积分: 410
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-04 12:39
文章分类

全部博文(36)

文章存档

2010年(1)

2009年(35)

我的朋友

分类: C/C++

2009-10-11 12:45:49

关于C函数指针,C++静态函数指针,非静态函数指针,std::mem_fun, 以及boost::function的小结。
                  
 Section I ================ general function pointer usage

function pointer can point to
1. general c-style function
2. template c-style function
3. general c++ static member function, which is totally the same with c-style function
4. c++ static member function which was used to delegate general non-static member function.
   the benefit of this usage is, we can use function pointer to base class to delegate member function of
   derived class.

all usage can be found in the following example. run it and get a feeling.

#include
#include
#include
#include

using namespace std;

class Base;
class A;

//c or c++ static member function
int (*function_pointer_c_style)(int,int);
//c++ non-static member function
int (A::*function_pointer_class_non_static_style)(int,int);
//c++, use static-style member function to delegate non-static member function
int (*function_pointer_class_static_delegate_style)(void*, int,int);

int sum(int a, int b)
{
    cout << "call non-template c-style function" << endl;
    cout << a << " + " << b << " = " << a + b << endl;
    cout << endl;
}

template
int sum(A a, B b)
{
    cout << "call template c-style function" << endl;
    cout << a << " + " << b << " = " << a + b << endl;
    cout << endl;
}

template
int multi(T a, int b)
{
    cout << "function pointer which point to template function" << endl;
    cout << a << " * " << b << " = " << a * b << endl;
    cout << endl;
}

class Base
{
public:
    int SumNonStatic( int a, int b)
    {
        cout << "call base class non-static member function" << endl;
        cout << "Base class: " << a << " + " << b << " = " << a + b << endl;
        cout << endl;
    }
};

class A : public Base
{
public:
    static int Sum(int a, int b)
    {
        cout << "call class static member function" << endl;
        cout << a << " + " << b << " = " << a + b << endl;
        cout << endl;
    }

    int SumNonStatic( int a, int b)
    {
        cout << "call class non-static member function" << endl;
        cout << "Derived class: " << a << " + " << b << " = " << a + b << endl;
        cout << endl;
    }

    static int Delegate(void*p, int a, int b)
    {
        //base to derived, use static_cast but dynamic_cast
        A* pa = static_cast(p);
        cout << "use static member function to delegate non-static member function. " << endl;
        pa->SumNonStatic(a, b);
        cout << endl;
    }
};

int main()
{
    function_pointer_c_style = sum;
    //the full format should be (*funtion_pointer)(para1, para2... )
    //the short format function_pointer(para1, para2...) is also right in C
    //but in c++, we must use (object.*function_pointer)(para1, para2...)
    (*function_pointer_c_style)(3,4);
    function_pointer_c_style = multi;
    function_pointer_c_style(3,4);

    function_pointer_c_style = &A::Sum;
    function_pointer_c_style(3,4);

    function_pointer_class_non_static_style = &A::SumNonStatic;
    A a;
    (a.*function_pointer_class_non_static_style)(3,4);
    
    function_pointer_class_static_delegate_style = &A::Delegate;
    function_pointer_class_static_delegate_style((void*)(&a), 3, 4);
    return 0;
}

@see for detailed instruction


                    Section II ================ std::mem_fun etc...

in following section, we will show the std::mem_fun and some related concept, such as bind1st and bind2st ..
the mechanisms of mem_fun is similar to

std::mem_fun or std::mem_fun_ref
1. only support non-parameter or one-parameter function, also bind1st, bind2nd ...
2. if we want to support arbitrary parameter, we can use to
   to customerize "mem_fun" of our-selves. but i recommend boost::function and boost::bind, which is
   very easy to use. see Section III

#include
#include

using namespace std;

class A
{
public:
    int NonPara()
    {
        cout << "member function without parameter!" << endl;
        cout << endl;
        return 0;
    }

    int OnePara(int para)
    {
        cout << "member function with one parameter:" << para << endl;
        cout << endl;
        return 0;
    }

    int TwoPara(int a, int b)
    {
        cout << "member function with two parameter:" << endl;
        cout << a << " + " << b << " = " << a + b << endl;
        cout << endl;
        return 0;
    }

    int MultiPara(int a, int b, int c)
    {
        cout << "member function with multi parameter:" << endl;
        cout << a << " + " << b << " + " << c << " = " << a + b + c << endl;
        cout << endl;
        return 0;
    }

};

int main()
{
    mem_fun_t std_mem_fun_non_para = mem_fun(&A::NonPara);
    //mem_fun_ref is similar to mem_fun, except that
    //mem_fun_ref require reference to object as its first parameter
    mem_fun_ref_t std_mem_fun_non_para_ref = mem_fun_ref(&A::NonPara);
    mem_fun1_t std_mem_fun_one_para = mem_fun(&A::OnePara);
    A a;
    std_mem_fun_non_para(&a);
    std_mem_fun_non_para_ref(a);
    std_mem_fun_one_para(&a, 3);

    //show bind1st.
    //next time we needn't pass object as first parameter, just pass the real para
    //such as call member function directly
    std::binder1st > std_mem_fun_non_para_with_object_bound =
        bind1st(std_mem_fun_one_para, &a);
    cout << "use bind1sh to bind object pointer" << endl;
    std_mem_fun_non_para_with_object_bound(2);
    cout << endl;

    return 0;
}


                    Section III ================ boost::function and boost::bind

the above difficulty can be easily solved by boost::function. boost::function is extended mem_fun,
and boost::bind is extended bind1st ...

see follow links:
//
//

#include
#include
#include
#include

using namespace std;

class A
{
public:
    int NonPara()
    {
        cout << "member function without parameter!" << endl;
        cout << endl;
        return 0;
    }

    int OnePara(int para)
    {
        cout << "member function with one parameter:" << para << endl;
        cout << endl;
        return 0;
    }

    int TwoPara(int a, int b)
    {
        cout << "member function with two parameter:" << endl;
        cout << a << " + " << b << " = " << a + b << endl;
        cout << endl;
        return 0;
    }

    int MultiPara(int a, int b, int c)
    {
        cout << "member function with multi parameter:" << endl;
        cout << a << " + " << b << " + " << c << " = " << a + b + c << endl;
        cout << endl;
        return 0;
    }

};

int main()
{
    //we don't use typedef for easy read. typedef should be used in practice
    A a;
    //use boost::function only, Note: A* must be a first parameter
    boost::function member_function_with_boost_function_only = &A::MultiPara;
    member_function_with_boost_function_only(&a, 3, 4, 5 ); // object as first parameter when call it

    //use boost::function and boost::bind. Note: returned function object have no A* as first para
    boost::function member_function_with_boost = boost::bind(&A::MultiPara, &a, _1, _2, _3);
    member_function_with_boost(3,4,5);//call directly, similar to member function

    return 0;
}
 
阅读(909) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

raymond19842009-10-11 12:47:50

终于明白了,看代码注释胜过看文章