函数指针--全局函数指针与类的函数指针(二)
本次对之前的说明做个补充,大体内容还是一样的。
这里对类里面的成员函数指针变量的使用继续进行了解,最主要的是希望能达到通过非静态成员指针变量来引用各自的非静态成员函数。
这样每个实例可以保存当前对象对应的功能操作,而无需再进行一些业务逻辑或者算法的计算,提高运行效率。
定义一个函数指针typedef int (T::*MFunc)(const int &, const int &);
在类T里面声明一个公有的非静态成员函数指针变量MFunc m_ProFunc;
1. 在类的非静态成员函数里面可以通过this指针对该成员变量进行操作(this->*m_ProFunc)(a, b);
2. 在类的静态成员函数和外部接口函数没有this指针,同时因为非静态函数成员含有this指针的原因,则无法通过该方式进行操作m_ProFunc(比如this->*m_ProFunc)。当你尝试使用实例对象进行操作时,例如给一个实例的形参T* t; 然后在函数里面通过指针操作该类(t->*m_ProFunc)(a, b),就无法通过编译,因为编译器做了函数识别与校验。是的,(t->*T::m_ProFunc)(a, b)和(t->T::*m_ProFunc)(a, b)这种方式在静态成员函数或外部接口函数都无法使用。
通过调测,发现了可以使用形参的方式来让编译器识别实例对象的非静态成员函数指针变量所调用的功能,这实在让人开心,因为这样就可以实现设计要求。
这样将函数指针变量当做实参传给调用的接口,继而在接口里面进行实际的功能调用。
注意:因为使用了指针变量,这就需要对非静态成员函数指针形参进行非空校验,避免程序coredump。
综上所述,对之前的代码进行了调整,希望可以提供一定的帮助和参考:)
- 全局函数指针的定义与调用。
- 假设一个函数Add(), 函数声明和定义如下:
int Add(const int &a, const int &b){ printf("Add\n"); return a + b;};
-
全局函数指针类型声明GFunc,函数指针TFunc1:
typedef int (*GFunc)(const int &, const int &);
GFunc TFunc1 = Add; //效果与显式TFunc1 = &Add一致。
TFunc1(a, b); //隐式调用Add,最终编译器会转为显式,按显式方式来处理 (*TFunc1)(a, b); //显式调用 Add
- 假设一个函数Add(), 函数声明和定义如下:
- 类的静态函数指针的定义与调用,包括在类的内部接口定义和外部接口定义,以及调用方法。
- 类的非静态函数指针的定义与调用,包括在类的内部接口定义和外部接口定义,以及调用方法。
- 假设一个类T的非静态公有函数Max(), 函数声明和定义如下:
int T::Max(const int &a, const int &b) {printf("T::Max\n");return a > b ? a : b;};
-
类T的非静态公有函数指针类型声明MFunc,公有函数指针成员变量m_ProFunc:
typedef int (T::*MFunc)(const int &, const int &);
MFunc m_ProFunc;
-
赋值与调用
m_ProFunc = &T::Max; //显式赋值,在类的非静态成员函数里面。在外部接口或者静态接口中,只能通过类的内部函数接口的函数参数方式进行赋值
(this->*m_ProFunc)(a, b); //显式调用,在类的非静态成员函数里面。在外部接口或者静态接口中,只能通过形参来进行调用,具体参考下面代码
-
通过操作类的函数地址赋值,需要加上类域(oparator class name). 注意这里不能使用&Test1.Max,只能使用类域取函数的地址,或者通过变量值。 Test1.ISetFunc(&T::Max); Test1.IGetFunc(a, b);
-
通过操作成员变量(oparator non-static member)赋值,这种可以更加灵活,先对变量进行赋值,然后直接操作该变量即可。注意这里不能使用(Test1.m_ProFunc)() Test1.m_ProFunc = &T::Min; Test1.ISetFunc(Test1.m_ProFunc); Test1.IGetFunc(a, b);
-
1 /* Author by sciapex@gmail.com */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 6 int Add(const int &a, const int &b){ printf("Add\n"); return a + b;}; 7 int Max(const int &a, const int &b){ printf("Max\n"); return a > b ? a : b;}; 8 int Min(const int &a, const int &b){ printf("Min\n"); return a < b ? a : b;}; 9 10 class T; 11 12 /*Pointer to non-static member function*/ 13 typedef int (T::*MFunc)(const int &, const int &); 14 15 /*Pointer to global function*/ 16 typedef int (*GFunc)(const int &, const int &); 17 18 class T { 19 public: 20 int m_Id; 21 22 MFunc m_ProFunc; 23 static MFunc m_sProFunc; 24 25 public: 26 T(): m_Id(0), m_ProFunc(NULL) {}; 27 28 int Max(const int &a, const int &b) {printf("T::Max\n");return a > b ? a : b;}; 29 int Min(const int &a, const int &b) {printf("T::Min\n");return a < b ? a : b;}; 30 static int Add(const int &a, const int &b) {printf("static T::Add\n");return a + b;}; 31 static int SMFunc(T *t, MFunc func, const int &a, const int &b) { 32 if (t == NULL) { 33 printf("Object is null!\n"); 34 return -1; 35 } 36 37 if (func == NULL) { 38 printf("MFunc is null!\n"); 39 return -1; 40 } 41 42 printf("That\'s SMFunc(%d:%d)\n", a, t->m_Id); 43 t->m_Id = a; 44 t->Min(a, b); 45 //(t->*m_ProFunc)(a, b); //error invalid use of member ‘T::m_ProFunc’ in static member function 46 (t->*func)(a, b); //ok 47 48 return t->m_Id; 49 }; 50 51 52 int Init(const int &type) { 53 m_Id = type; 54 if (type == 1) { 55 m_ProFunc = &T::Max; 56 } else if (type == 2) { 57 //m_ProFunc = &(this->Min); // error 58 m_ProFunc = &T::Min; 59 } else { 60 printf("unkown type\n"); 61 return -1; 62 } 63 64 return 0; 65 } 66 67 /*Internal interface function,Encapsulate non-static member functions*/ 68 int IResult(MFunc func, const int &a, const int &b){ 69 printf("That\'s IResult:(%d)--->", m_Id); 70 return (this->*func)(a, b); 71 } 72 73 int ISetFunc(MFunc func){ 74 m_ProFunc = func; //Reset func 75 } 76 77 int IGetFunc(const int &a, const int &b) { 78 //(*m_ProFunc)(a, b); // error:invalid use of unary ‘*’ on pointer to member 79 (this->*m_ProFunc)(a, b); // ok 80 } 81 82 }; 83 84 MFunc T::m_sProFunc = &T::Min; 85 86 /*External interface function,Encapsulate non-static member functions*/ 87 int MResult(T* p, MFunc func, const int &a, const int &b) 88 { 89 printf("That\'s Ext MResult:(%d)--->", p->m_Id); 90 p->Min(a, b); 91 92 if (func == NULL) { 93 printf("Pointer is null!\n"); 94 return -1; 95 } 96 97 // *(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) (...)’ 98 // (p->*T::m_ProFunc)(a, b); invalid use of non-static data member ‘T::m_ProFunc’ 99 // (p->T::*m_ProFunc)(a, b); ‘m_ProFunc’ was not declared in this scope 100 // (p->*m_ProFunc)(a, b); ‘m_ProFunc’ was not declared in this scope 101 return (p->*func)(a, b); 102 } 103 104 /*External interface function,Encapsulate global or static member functions*/ 105 int GResult(GFunc func, const int &a, const int &b) 106 { 107 printf("That\'s Ext GResult--->"); 108 Add(a, b); 109 T::Add(a, b); 110 111 return (*func)(a, b); 112 } 113 114 int main(int argc, char *argv[]) 115 { 116 printf("Program:Test pointer to funtion. Author by sciapex!\n"); 117 int a = 1; 118 int b = 2; 119 120 /* 1st way:general and static member funtion */ 121 printf("Test 1st................!\n"); 122 GFunc TFunc1 = Add; //like as TFunc1 = &Add; 123 GFunc TFunc2 = &T::Add; 124 125 TFunc1(a, b); 126 (*TFunc2)(a, b); //like as (*TFunc1)(a, b); 127 (*TFunc2)(a, b); 128 129 /* 2nd way:non-static member funtion */ 130 printf("Test 2nd................!\n"); 131 T Test1; 132 133 //Test1.Result(&Test1.Max(), a, b); error 134 //Test1.Result(&T::Min, a, b); error 135 //Test1.Result(T::Min, a, b); error 136 Test1.IResult(&T::Max, a, b); 137 Test1.IResult(&T::Min, a, b); 138 139 Test1.Init(1); 140 Test1.IGetFunc(a, b); 141 142 Test1.Init(2); 143 Test1.IGetFunc(a, b); 144 145 // oparator class name 146 printf("2nd:class name................!\n"); 147 Test1.ISetFunc(&T::Max); 148 Test1.IGetFunc(a, b); 149 150 // oparator non-member 151 printf("2nd:non-member................!\n"); 152 Test1.m_ProFunc = &T::Min; 153 Test1.ISetFunc(Test1.m_ProFunc); 154 Test1.IGetFunc(a, b); 155 156 T::SMFunc(&Test1, &T::Max, 100, b); 157 T::SMFunc(&Test1, &T::Min, 200, b); 158 T::SMFunc(&Test1, Test1.m_ProFunc, 300, b); 159 /* 3th way:external funtion */ 160 printf("Test 3rd................!\n"); 161 T T1; 162 163 //MResult(T1, T1.Max, a, b); error 164 //MResult(&T1, T::Max, a, b); error 165 T1.Init(0); 166 MResult(&T1, &T::Max, a, b); 167 T1.Init(1); 168 MResult(&T1, &T::Min, a, b); 169 T1.Init(2); 170 MResult(&T1, T1.m_ProFunc, a, b); 171 172 GResult(TFunc1, a, b); 173 GResult(TFunc2, a, b); 174 175 printf("All Done!\n"); 176 return (EXIT_SUCCESS); 177 }
Ubuntu输出
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 2th:class name................! T::Max 2nd:non-member................! 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 3rd................! 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!