zoukankan      html  css  js  c++  java
  • C++ Function Pointer

    Regarding their syntax, there are two different types of function pointers: On the one hand there are pointers to ordinary C functions or to static C++ member functions. On the other hand there are pointers to non-static C++ member functions. The basic difference is that all pointers to non-static member functions need a hidden argument: The this-pointer to an instance of the class. Always keep in mind: These two types of function pointers are incompatible with each other.

    Assign an address to a Function Pointer

    It's quite easy to assign the address of a function to a function pointer. You simply take the name of a suitable and known function or member function. Although it's optional for most compilers you should use the address operator & infront of the function's name in order to write portable code. You may have got to use the complete name of the member function including class-name and scope-operator (::). Also you have got to ensure, that you are allowed to access the function right in scope where your assignment stands.


    // 2.3 assign an address to the function pointer
    // Note: Although you may ommit the address operator on most compilers
    // you should always use the correct way in order to write portable code.

    // C
    int DoIt (float a, char b, char c){ printf("DoIt\n"); return a+b+c; }
    int DoMore(float a, char b, char c)const{ printf("DoMore\n"); return a-b+c; }

    pt2Function = DoIt; // short form
    pt2Function = &DoMore; // correct assignment using address operator


    // C++
    class TMyClass
    {
    public:
    int DoIt(float a, char b, char c){ cout << "TMyClass::DoIt"<< endl; return a+b+c;};
    int DoMore(float a, char b, char c) const
    { cout << "TMyClass::DoMore" << endl; return a-b+c; };

    /* more of TMyClass */
    };

    pt2ConstMember = &TMyClass::DoMore; // correct assignment using address operator
    pt2Member = &TMyClass::DoIt; // note: <pt2Member> may also legally point to &DoMore

    Comparing Function Pointers

    You can use the comparison-operators (==, !=) the same way as usual. In the following example it is checked, whether pt2Function and pt2Member actually contain the address of the functions DoIt and TMyClass::DoMore. A text is shown in case of equality.

    // 2.4 comparing function pointers

    // C
    if(pt2Function >0){ // check if initialized
    if(pt2Function == &DoIt)
    printf("Pointer points to DoIt\n"); }
    else
    printf("Pointer not initialized!!\n");


    // C++
    if(pt2ConstMember == &TMyClass::DoMore)
    cout << "Pointer points to TMyClass::DoMore" << endl;

    Calling a Function using a Function Pointer

    In C you call a function using a function pointer by explicitly dereferencing it using the * operator. Alternatively you may also just use the function pointer's instead of the funtion's name. In C++ the two operators .* resp. ->* are used together with an instance of a class in order to call one of their (non-static) member functions. If the call takes place within another member function you may use the this-pointer.


    // 2.5 calling a function using a function pointer
    int result1 = pt2Function (12, 'a', 'b'); // C short way
    int result2 = (*pt2Function) (12, 'a', 'b'); // C

    TMyClass instance1;
    int result3 = (instance1.*pt2Member)(12, 'a', 'b'); // C++
    int result4 = (*this.*pt2Member)(12, 'a', 'b'); // C++ if this-pointer can be used

    TMyClass* instance2 = new TMyClass;
    int result4 = (instance2->*pt2Member)(12, 'a', 'b'); // C++, instance2 is a pointer
    delete instance2;

    How to Pass a Function Pointer as an Argument ?

    You can pass a function pointer as a function's calling argument. You need this for example if you want to pass a pointer to a callback function. The following code shows how to pass a pointer to a function which returns an int and takes a float and two char:

    //------------------------------------------------------------------------------------
    // 2.6 How to Pass a Function Pointer

    // <pt2Func> is a pointer to a function which returns an int and takes a float and two char
    void PassPtr(int (*pt2Func)(float, char, char))
    {
    int result = (*pt2Func)(12, 'a', 'b'); // call using function pointer
    cout << result << endl;
    }

    // execute example code - 'DoIt' is a suitable function like defined above in 2.1-4
    void Pass_A_Function_Pointer()
    {
    cout << endl << "Executing 'Pass_A_Function_Pointer'" << endl;
    PassPtr(&DoIt);
    }

    How to Return a Function Pointer ?

    It's a little bit tricky but a function pointer can be a function's return value. In the following example there are two solutions of how to return a pointer to a function which is taking two float arguments and returns a float. If you want to return a pointer to a member function you have just got to change the definitions/declarations of all function pointers.


    //------------------------------------------------------------------------------------
    // 2.7 How to Return a Function Pointer
    // 'Plus' and 'Minus' are defined above. They return a float and take two float


    // Direct solution: Function takes a char and returns a pointer to a
    // function which is taking two floats and returns a float. <opCode>
    // specifies which function to return
    float (*GetPtr1(const char opCode))(float, float)
    {
    if(opCode == '+')
    return &Plus;
    else
    return &Minus; // default if invalid operator was passed
    }


    // Solution using a typedef: Define a pointer to a function which is taking
    // two floats and returns a float
    typedef float(*pt2Func)(float, float);

    // Function takes a char and returns a function pointer which is defined
    // with the typedef above. <opCode> specifies which function to return
    pt2Func GetPtr2(const char opCode)
    {
    if(opCode == '+')
    return &Plus;
    else
    return &Minus; // default if invalid operator was passed
    }


    // Execute example code
    void Return_A_Function_Pointer()
    {
    cout << endl << "Executing 'Return_A_Function_Pointer'" << endl;

    // define a function pointer and initialize it to NULL
    float (*pt2Function)(float, float) = NULL;

    pt2Function=GetPtr1('+'); // get function pointer from function 'GetPtr1'
    cout << (*pt2Function)(2, 4) << endl; // call function using the pointer


    pt2Function=GetPtr2('-'); // get function pointer from function 'GetPtr2'
    cout << (*pt2Function)(2, 4) << endl; // call function using the pointer
    }
    How to Use Arrays of Function Pointers ?

    Operating with arrays of function pointers is very interesting. This offers the possibility to select a function using an index. The syntax appears difficult, which frequently leads to confusion. Below you find two ways of how to define and use an array of function pointers in C and C++. The first way uses a typedef, the second way directly defines the array. It's up to you which way you prefer.

    //------------------------------------------------------------------------------------
    // 2.8 How to Use Arrays of Function Pointers

    // C ---------------------------------------------------------------------------------

    // type-definition: 'pt2Function' now can be used as type
    typedef int (*pt2Function)(float, char, char);

    // illustrate how to work with an array of function pointers
    void Array_Of_Function_Pointers()
    {
    printf("\nExecuting 'Array_Of_Function_Pointers'\n");

    // define arrays and ini each element to NULL, <funcArr1> and <funcArr2> are arrays
    // with 10 pointers to functions which return an int and take a float and two char

    // first way using the typedef
    pt2Function funcArr1[10] = {NULL};

    // 2nd way directly defining the array
    int (*funcArr2[10])(float, char, char) = {NULL};


    // assign the function's address - 'DoIt' and 'DoMore' are suitable functions
    // like defined above in 2.1-4
    funcArr1[0] = funcArr2[1] = &DoIt;
    funcArr1[1] = funcArr2[0] = &DoMore;

    /* more assignments */

    // calling a function using an index to address the function pointer
    printf("%d\n", funcArr1[1](12, 'a', 'b')); // short form
    printf("%d\n", (*funcArr1[0])(12, 'a', 'b')); // "correct" way of calling
    printf("%d\n", (*funcArr2[1])(56, 'a', 'b'));
    printf("%d\n", (*funcArr2[0])(34, 'a', 'b'));
    }


    // C++ -------------------------------------------------------------------------------

    // type-definition: 'pt2Member' now can be used as type
    typedef int (TMyClass::*pt2Member)(float, char, char);

    // illustrate how to work with an array of member function pointers
    void Array_Of_Member_Function_Pointers()
    {
    cout << endl << "Executing 'Array_Of_Member_Function_Pointers'" << endl;

    // define arrays and ini each element to NULL, <funcArr1> and <funcArr2> are
    // arrays with 10 pointers to member functions which return an int and take
    // a float and two char

    // first way using the typedef
    pt2Member funcArr1[10] = {NULL};

    // 2nd way of directly defining the array
    int (TMyClass::*funcArr2[10])(float, char, char) = {NULL};


    // assign the function's address - 'DoIt' and 'DoMore' are suitable member
    // functions of class TMyClass like defined above in 2.1-4
    funcArr1[0] = funcArr2nd use an array of function pointers in C and C++. The first way uses a typedef, the second way directly defines the array. It's up to you which way you prefer.


    [1] = &TMyClass::DoIt;
    funcArr1[1] = funcArr2[0] = &TMyClass::DoMore;
    /* more assignments */

    // calling a function using an index to address the member function pointer
    // note: an instance of TMyClass is needed to call the member functions
    TMyClass instance;
    cout << (instance.*funcArr1[1])(12, '
    a', 'b') << endl;
    cout << (instance.*funcArr1[0])(12, '
    a', 'b') << endl;
    cout << (instance.*funcArr2[1])(34, '
    a', 'b') << endl;
    cout << (instance.*funcArr2[0])(89, '
    a', 'b') << endl;
    }
    How to Implement a Callback to a non-static C++ Member Function ?
    The Wrapper Approach

    Pointers to non-static members are different to ordinary C function pointers since they need the this-pointer of a class object to be passed. Thus ordinary function pointers and non-static member functions have different and incompatible signatures! If you just want to callback to a member of a specific class you just change your code from an ordinary function pointer to a pointer to a member function. But what can you do, if you want to callback to a non-static member of an arbitrary class? It's a little bit difficult. You need to write a static member function as a wrapper. A static member function has the same signature as a C function! Then you cast the pointer to the object on which you want to invoke the member function to void* and pass it to the wrapper as an additional argument or via a global variable. If you use a global variable it is very important, that you make sure that it will always point to the correct object! Of course you've also got to pass the calling arguments for the member function. The wrapper casts the void-pointer to a pointer to an instance of the corresponding class and calls the member function. Below you find two examples.
    Example A: Pointer to a class instance is passed as an additional argument

    The function DoItA does something with objects of the class TClassA which implies a callback. Therefore a pointer to an object of class TClassA and a pointer to the static wrapper function TClassA::Wrapper_To_Call_Display are passed to DoItA. This wrapper is the callback-function. You can write arbitrary other classes like TClassA and use them with DoItA as long as these other classes provide the necessary functions. Nore: This solution may be useful if you design the callback interface yourself. It is much better than the second solution which uses as global variable.

    Using Polymorphism and Virtual Functions Instead of Function Pointers (C++)

    Function pointer doesn’t support using the base virtual function pointer to refer to the same virtual function in devired class, as the siganuture is different between base and devired.

    typedef int (Base::*Func)(int);
    Func func = &Devired::ThreadFun; // wrong
    Devired d;
    cout<<(d.*func)(5)<<endl; // fail

    You can often avoid the need for explicit function pointers by using virtual functions. For instance, you could write a sorting routine that takes a pointer to a class that provides a virtual function called compare:

    But Are You Really Not Using Function Pointers?

    Virtual functions are implemented behind the scenes using function pointers, so you really are using function pointers--it just happens that the compiler makes the work easier for you. Using polymorphism can be an appropriate strategy (for instance, it's used by Java), but it does lead to the overhead of having to create an object rather than simply pass in a function pointer.

  • 相关阅读:
    Tensorflow实战系列之三:
    Tensorflow实战系列之二:
    scala映射和元组
    scala函数
    scala基础
    Hadoop Eclipse 插件制作以及安装
    理解HBase
    理解HDFS
    Hadoop入门学习路线
    日志框架Log4j
  • 原文地址:https://www.cnblogs.com/rogerroddick/p/3073083.html
Copyright © 2011-2022 走看看