函数指针
@
前言:
class Thread {
public:
Thread() {}
~Thread() {}
static void testThread() {
cout << "test thread" << endl;
}
static void start() {
std::thread t1(testThread);
t1.join();
}
};
int main()
{
Thread t;
t.start();
return 0;
}
在类内创建一个线程时,如果testThread是非静态的,则编译会报错:
reference to non-static member function must be called; did you mean to call it with no arguments?
no matching constructor for initialization of 'std::thread'
原因是由于:非静态成员函数testThread有一个隐式的参数this指针,而静态成员函数没有this指针
函数指针定义
每一个函数都占用一段内存单元,它们有一个起始地址,指向函数入口地址的指针称为函数指针。
数据类型 (*指针变量名)(参数表);
注意区别:
void (*p)(int a, int b); //p是一个指向函数的指针变量
void *p(int a, int b); //p是函数名,此函数的返回值类型为void指针
函数指针的初始化和赋值
1.定义一个函数
void fun(int a, int b) {}
2.函数指针初始化和赋值
void (*pFun)(int a, int b) = fun;
可以使用typedef
typedef void (*pFunctionType)(int a, int b);
pFunctionType pFun = fun;
pFunctionType pFun = &fun; // 在C/C++里函数名就是地址,所以上面两个等价,都可以给函数指针赋值。
函数调用
可以直接使用指向函数的指针调用函数
fun(5, 6);
(*pFun)(5, 6);
(*pFunctionType)(5, 6);
注意:
- 指向不同函数类型的指针之间不存在转换规则。
- 可以为函数指针赋一个 nullptr或者0的整型常量表达式,表示该指针没有指向任何一个函数。
函数指针作为形参
例如:
#include<iostream>
using namespace std;
typedef int(*addFcn)(int a, int b);
int addFunction(int a, int b) {
return (a + b);
}
void test(int a, int b, int(*pf)(int a, int b)) {
cout << pf(a, b) << endl;
}
int main()
{
addFcn pf = addFunction;
test(3, 4, pf);
return 0;
}
/*
输出结果:7
*/
函数指针作为返回值
#include<iostream>
using namespace std;
int demo(int a, int b) {
return a*b;
}
// ff是一个函数,有一个形参x,返回结果是一个函数指针int(*)(int,int)
int (*ff(int x))(int, int) {
cout << x << endl;
return demo;
}
int main()
{
int a = 5;
cout << ff(2)(a, a)<< endl;
return 0;
}
/*
输出结果:
2
25
*/
指向类的成员函数的指针
1)指向类非静态成员函数的指针
指向类非静态成员函数的指针与普通函数指针的区别在于: 不仅要匹配函数的参数类型和个数以及返回值类型,还要匹配该函数指针所属的类类型。
声明:与普通函数相比,指向类的成员函数的指针只需要在指针前加上类类型即可,格式为:
typedef 返回值 (类名::*指针类型名)(参数列表);
赋值:只需要用类的成员函数地址赋值即可,格式为:
指针类型名 指针名 = &类名::成员函数名; //加了&,才会认为是获取函数指针,不然,编译器会认为是调用成员函数
调用:针对调用的对象是对象还是指针,分别用.和->进行调用,格式为:
(类对象.*指针名)(参数列表);
(类指针->*指针名)(参数列表);
// 注意:这里的前面一对括号是很重要的,因为()的优先级高于成员操作符指针的优先级。
2)指向类静态成员函数的指针
类的静态成员是不依赖于具体对象的,所有实例化的对象都共享同一个静态成员,所以静态成员函数也没有this指针的概念。
所以,指向类的静态成员函数的指针就是普通的指针。
例子:
#include<iostream>
using namespace std;
typedef void (*STATICFUNCPTR)(int a, int b); // 静态成员函数指针
class A;
typedef void (A::*NONSTATICFUNCPTR)(int a, int b); //非静态成员函数指针
class A
{
public:
void nonStaticFunc(int a, int b)
{
cout<< "nonStaticFunc result: " << a + b << endl;
}
static void staticFunc(int a, int b)
{
cout<< "staticFunc result: " << a * b << endl;
}
};
int main()
{
NONSTATICFUNCPTR nonStaticFuncPtr= &A::nonStaticFunc;
STATICFUNCPTR staticFuncPtr = &A::staticFunc;
A a;
(a.*nonStaticFuncPtr)(3, 4); //非静态函数指针通过对象调用
A *aPtr = new A;
(aPtr->*nonStaticFuncPtr)(5, 6); //非静态函数指针通过指针调用
(*staticFuncPtr)(5, 6); //静态函数指针调用
return 0;
}
/*
输出结果:
nonStaticFunc result: 7
staticFunc result: 12
nonStaticFunc result: 11
staticFunc result: 30
*/
指向类的数据成员的指针
类的非静态成员变量需要判断下列两项是否一致,而静态成员不依赖this指针,不需要判断b
a)数据成员类型
b)所属的类类型
例子
#include <iostream>
using namespace std;
class A;
typedef int (A::*NONSTATICDATAPTR); //定义类的非静态数据成员指针
typedef const int *STATICDATAPTR; //定义类的静态数据成员指针
class A
{
public:
A(int a):m_nonStaticData(a){}
int m_nonStaticData;
static int m_staticData;
};
int A::m_staticData = 6;
int main()
{
NONSTATICDATAPTR nonStaticDataPtr= &A::m_nonStaticData;
STATICDATAPTR staticDataPtr = &A::m_staticData;
A a(10);
cout << "(non static) obj: " << a.*nonStaticDataPtr << endl; //通过对象引用
A *aPtr = new A(100);
cout << "(non static) pointer:" << aPtr->*nonStaticDataPtr << endl; //通过指针引用
cout << "(static): " << *staticDataPtr << endl;
return 0;
}
/*输出结果:
(non static) obj: 10
(non static) pointer:100
(static): 6
*/