前言

函数指针:函数指针是指向函数的指针变量。

1
2
3
4
int add(int a,int b){
return a + b;
}
int (*pAdd)(int, int) = add;

正文

1
2
3
4
5
6
7
8
9
10
class Box{
public:
void test(){
std::cout << "test!\n";
}

void hhh(){
std::cout << "hhh!\n";
}
};

如果按照正常逻辑,想让函数指针指向一个函数

1
void (*pTest)() = test;

这样肯定是不对的,因为这个test是类的成员函数而不是所谓的全局函数,如果全局函数都没有,那么这个test就是一个未定义标识符
有的人可能会想到作用域问题。

1
void (*pTest)() = Box::test;

显然这也不是行的,毕竟类没有实例化,成员函数也非静态。
成员函数最关键的是它内部可以调用this指针,这是普通的函数无法做到的。

解决办法也是相对的,在报错的时候看到提示void (Box::*)()不能用于初始化void(*)()的实体

1
void (Box::*pTest)() = Box::test;

那么显然它是要你在函数指针那块也要加上作用域。


玩点话的,之前学过typedef也就是自定义类型名

1
typedef void(Box:: *pBox)();

然后就可以玩了

1
2
3
pBox pb;
Box *box = new Box();
(box->*pb)();

不过这里会报错,因为pb没有初始化。
学类的时候,我们知道成员函数和成员变量有所区别,成员变量需要实例化才能调用,而成员函数编译的时候就分配好了地址,所以实例化多少类,成员函数地址都是一样的。除非说static,那种情况下既没有this指针,又在预编译阶段就完成了,可以直接通过类的作用域访问。

因此这里直接让他指向box其中的一个成员函数。

1
2
3
pBox pb = &Box::test;
Box *box = new Box();
(box->*pb)();

随便用一个,毕竟就俩。

可以看到,成功指向test,然后通过box指向指针解引用完成了函数调用。

因为没有参数列表可能看着很古怪

值得一提是,因为我们的类函数指针做了类限制,所以他只能指向这个类中的函数,普通的函数它是不能指向的。


有的时候这个函数指针也可能直接作为类的成员变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Box;                              //声明
typedef void(Box:: *pBox)();

class Box{
public:
void test(){
std::cout << "test!\n";
}

void hhh(){
std::cout << "hhh!\n";
}
Box(){
phhh = &Box::hhh;
(this->*phhh)();
}
pBox phhh;
};

这样一来

可以看到效果都差不多。


然后就是static成员函数问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Box{
public:
static void func(){
std::cout << "func!\n";
}

void test(){
std::cout << "test!\n";
}

void hhh(){
std::cout << "hhh!\n";
}
Box(){
phhh = &Box::hhh;
(this->*phhh)();
}
pBox phhh;
};

typedef void(*pFun)();

正常情况下可以这样调用。

通过定义的函数指针就可以用这种方式调用。
因为静态成员函数没有this指针,所以不需要在通过指针指向解引用出成员函数


结语

看着用吧,知道就行。