欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

函数指针--全局函数指针与类的函数指针(二)

程序员文章站 2022-04-04 09:28:49
本次对之前的说明做个补充,大体内容还是一样的 这里对类里面的成员函数指针变量的使用继续进行了解,最主要的是希望能达到通过非静态成员指针变量来引用各自的非静态成员函数。 这样每个实例可以保存当前对象对应的功能操作,而无需再进行一些业务逻辑或者算法的计算,提高运行效率。 定义一个函数指针typedef ......

本次对之前的说明做个补充,大体内容还是一样的

 

这里对类里面的成员函数指针变量的使用继续进行了解,最主要的是希望能达到通过非静态成员指针变量来引用各自的非静态成员函数。

这样每个实例可以保存当前对象对应的功能操作,而无需再进行一些业务逻辑或者算法的计算,提高运行效率。

定义一个函数指针typedef int (T::*MFunc)(const int &, const int &);

在类T里面声明一个公有的非静态成员函数指针变量MFunc m_ProFunc;

1. 在类的非静态成员函数里面可以通过this指针对该成员变量进行操作(this->*m_ProFunc)(a, b);

2. 在类的静态成员函数外部接口函数没有this指针,则无法通过该方式进行操作m_ProFunc。当你尝试使用实例对象进行操作时,例如给一个实例的形参T* t; 然后在函数里面通过指针操作该类(t->*m_ProFunc)(a, b);就无法通过编译,因为编译器无法正确识别该表达式。是的,(t->*T::m_ProFunc)(a, b)和(t->T::*m_ProFunc)(a, b)这种方式在静态成员函数或外部接口函数都无法使用。

 

通过调测,发现了可以使用形参的方式来让编译器识别实例对象的非静态成员函数指针变量所调用的功能,这实在让人开心,因为这样就可以实现设计要求。

这样将函数指针变量当做实参传给调用的接口,继而在接口里面进行实际的功能调用。

注意:因为使用了指针变量,这就需要对非静态成员函数指针形参进行非空校验,避免程序coredump。

 

综上所述,对之前的代码进行了调整,希望可以提供一定的帮助和参考:)

/* Author by sciapex@gmail.com */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int Add(const int &a, const int &b){ printf("Add\n"); return a + b;};
int Max(const int &a, const int &b){ printf("Max\n"); return a > b ? a : b;};
int Min(const int &a, const int &b){ printf("Min\n"); return a < b ? a : b;};

class T;

/*Pointer to non-static member function*/
typedef int (T::*MFunc)(const int &, const int &);

/*Pointer to global function*/
typedef int (*GFunc)(const int &, const int &);

class T {
    public:
        int m_Id;

        MFunc m_ProFunc;
        static MFunc m_sProFunc;

    public:
        T(): m_Id(0), m_ProFunc(NULL) {};

        int Max(const int &a, const int &b) {printf("T::Max\n");return a > b ? a : b;};
        int Min(const int &a, const int &b) {printf("T::Min\n");return a < b ? a : b;};
        static int Add(const int &a, const int &b) {printf("static T::Add\n");return a + b;};
        static int SMFunc(T *t, MFunc func, const int &a, const int &b) {
            if (t == NULL) {
                printf("Object is null!\n");
                return -1;
            }

            if (func == NULL) {
                printf("MFunc is null!\n");
                return -1;
            }

            printf("That's SMFunc(%d:%d)\n", a, t->m_Id);
            t->m_Id = a;
            t->Min(a, b);
            //(t->*m_ProFunc)(a, b); //error invalid use of member ‘T::m_ProFunc’ in static member function
            (t->*func)(a, b);        //ok

            return t->m_Id;
        };


        int Init(const int &type) {
            m_Id = type;
            if (type == 1) {
                m_ProFunc = &T::Max;
            } else if (type == 2) {
                //m_ProFunc = &(this->Min);  // error
                m_ProFunc = &T::Min;
            } else {
                printf("unkown type\n");
                return -1;
            }

            return 0;
        }

        /*Internal interface function,Encapsulate non-static member functions*/
        int IResult(MFunc func, const int &a, const int &b){
            printf("That's IResult:(%d)--->", m_Id);
            return (this->*func)(a, b);
        }

        int Run(const int &a, const int &b) {
            //(*m_ProFunc)(a, b);          // error:invalid use of unary ‘*’ on pointer to member
            (this->*m_ProFunc)(a, b);      // ok
         }

};

MFunc T::m_sProFunc = &T::Min;

/*External interface function,Encapsulate non-static member functions*/
int MResult(T* p, MFunc func, const int &a, const int &b)
{
    printf("That's Ext MResult:(%d)--->", p->m_Id);
    p->Min(a, b);

    if (func == NULL) {
        printf("Pointer is null!\n");
        return -1;
    }
        
    // *(p->m_ProFunc)(a, b);  must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘p->T::m_ProFunc (...)’, e.g. ‘(... ->* p->T::m_ProFunc) (...)’
    // (p->*T::m_ProFunc)(a, b);  invalid use of non-static data member ‘T::m_ProFunc’
    // (p->T::*m_ProFunc)(a, b);  ‘m_ProFunc’ was not declared in this scope
    // (p->*m_ProFunc)(a, b);  ‘m_ProFunc’ was not declared in this scope
    return (p->*func)(a, b);
}

/*External interface function,Encapsulate global or static member functions*/
int GResult(GFunc func, const int &a, const int &b)
{
    printf("That's Ext GResult--->");
    Add(a, b);
    T::Add(a, b);

    return (*func)(a, b);
}

int main(int argc, char *argv[])
{
    printf("Program:Test pointer to funtion. Author by sciapex!\n");
    int a = 1;
    int b = 2;

    /* 1st way:general and static member funtion */
    printf("Test 1st................!\n");
    GFunc TFunc1 = Add;    //like as TFunc1 = &Add;
    GFunc TFunc2 = &T::Add;

    TFunc1(a, b);
    (*TFunc2)(a, b);       //like as (*TFunc1)(a, b);
    (*TFunc2)(a, b);

    /* 2nd way:non-static member funtion */
    printf("Test 2nd................!\n");
    T Test1;

    //Test1.Result(&Test1.Max(), a, b);  error
    //Test1.Result(&T::Min, a, b);    error
    //Test1.Result(T::Min, a, b);     error
    Test1.IResult(&T::Max, a, b);
    Test1.IResult(&T::Min, a, b);

    Test1.Init(1);
    Test1.Run(a, b);

    Test1.Init(2);
    Test1.Run(a, b);

    T::SMFunc(&Test1, &T::Max, 100, b);
    T::SMFunc(&Test1, &T::Min, 200, b);
    T::SMFunc(&Test1, Test1.m_ProFunc, 300, b);
    /* 3th way:external funtion */
    printf("Test 3th................!\n");
    T T1;

    //MResult(T1, T1.Max, a, b);  error
    //MResult(&T1, T::Max, a, b); error
    T1.Init(0);
    MResult(&T1, &T::Max, a, b);
    T1.Init(1);
    MResult(&T1, &T::Min, a, b);
    T1.Init(2);
    MResult(&T1, T1.m_ProFunc, a, b);

    GResult(TFunc1, a, b);
    GResult(TFunc2, a, b);

    printf("All Done!\n");
    return (EXIT_SUCCESS);
}

输出

root@ubuntu:~/Test/test/
$ a.out
Program:Test pointer to funtion. Author by sciapex!
Test 1st................!
Add
static T::Add
static T::Add
Test 2nd................!
That's IResult:(0)--->T::Max
That's IResult:(0)--->T::Min
T::Max
T::Min
That's SMFunc(100:2)
T::Min
T::Max
That's SMFunc(200:100)
T::Min
T::Min
That's SMFunc(300:200)
T::Min
T::Min
Test 3th................!
unkown type
That's Ext MResult:(0)--->T::Min
T::Max
That's Ext MResult:(1)--->T::Min
T::Min
That's Ext MResult:(2)--->T::Min
T::Min
That's Ext GResult--->Add
static T::Add
Add
That's Ext GResult--->Add
static T::Add
static T::Add
All Done!