更新时间:2017-07-11 00:58:20浏览次数:1+次
show();
A::show();
那么类成员函数如何使用呢?当然,我们需要对象的支持,所以先要创建一个对象,然后再使用。如:A a;
a.show();
int show();
int (*pshow)();
我们将show替换为(*pshow)就达到效果了。为什么要加()呢?反过来想一下,如果不要(),你看看是什么效果:int *pshow1();
这不就是一个返回int*的函数嘛!哪来的函数指针了呢?所以,括号就是为了实现声明函数指针的。那么为什么要声明函数指针呢?可不可以不要*呢?如果你不要*号,就是这样的效果:int (pshow2)();//即 int pshow2();
这不就是声明普通的函数嘛。所以函数指针是可以指向函数的。所以,pshow = show;
这样就顺理成章了。这就是C++语法的一套。当你不理解的时候,你可以反过来拆,反过来想,结果也就得到了一致的效果。语法的实现过程,也就是要让不同的规则有不同的表示,然后拆来拆去最后还是统一的。pshow();
(*pshow)();
这两句函数调用,是否有错误呢?第一个是指针可以直接调用,和指针使用变量规则相似。而第二个呢?因为pshow是函数指针,所以取值之后,就得到函数,这样再调用函数,也说得过去。所以C++中这两种用法都是可以的。不同的人有不同的看法,只是C++语言进行了折中,婆说婆有理公说公有理,那就保持和睦共存好了。int test();
int (*ptest)();
ptest = test;
就将函数名当做变量赋值就行了。因为函数名就是函数地址,所以可以直接给指针,而不需要取地址了。那么对于类静态函数呢?既然类静态函数与C函数只是在于作用域不同而已,所以在用法也就是作用域的差异而已,只要在函数前面带上类作用域就行了。如:ptest = A::show();
当然,你需要事先声明类和类静态函数。对于普通函数指针来说,不需要做任何作用域的声明,就是全局的。所以对普通函数指针来说,可以指向普通的C函数,还可以指向各个类的静态函数。void (A::*PFUN_CLASS)();//动态函数指针
void (*PFUN)();//静态函数指针
而在用函数指针传参的时候,静态函数指针和动态函数指针也是有差异的。我们来看一个函数的声明:void show2(PFUN_CLASS pfun_class,PFUN pfun,PFUN_B pfun_b);
第一个参数是动态函数指针,第二个是普通函数指针,第三个是指向B类的静态函数指针。而他们的传参是这样的:show2(&A::show3,show,B::showb);
而动态函数指针的直接赋值也就是这样的:pfun_class = &A::show3;
第二个我们很好理解,第三个和第一个的差别就在于一个&符号。我们来想想这个差别是为什么?对于类静态函数的使用,我们是不是都是直接使用类作用域来使用的!所以呢,B::showb的写法也就很自然而然的了。既然如此,我们当然不能再用这样的语法来支持动态函数指针的赋值了吧,不然还怎么区分呢?而使用&也是有原因的。对于类的成员函数,可以进行函数重载,也就是说,同一个函数名可以有很多个参数列表的版本,这样一来,一个函数名可以列出一大堆的函数。那么此时,你用A::show3也无法指定是某一个成员函数吧。那要如何最终确定赋值给动态函数指针的值的呢?当然就是动态确定的啦。当传参进去的时候,自然就可以知道被传入的函数的类型了,然后就可以在成员函数重载版本列表里寻找一个匹配的版本咯。如果没有匹配的版本,自然也就类型不匹配。所以,这个参数我们使用取地址符来表示得到重载成员函数列表的地址,在需要的时候查询列表得到匹配的版本,这样是不是就顺理成章了呢!!void (A::*PFUN_CLASS)();//动态函数指针
void (*PFUN)();//静态函数指针
void show(){}
void A::test(){}
void B::T()
{
PFUN = show;//普通函数指针
PFUN();
PFUN_CLASS=&A::test();//动态函数指针
PFUN_CLASS();//???这样对吗??
}
我们先不直接讨论上面这个对不对,先来看看普通的成员函数的调用。如:void A::show2(PFUN_CLASS pfun_class,PFUN pfun,PFUN_B pfun_b)
{
test();
this->test();
(this->test)();
}
以上三种写法都是对的吗?当然是对的。在类成员函数中都隐藏这一个this对象指针,也就是此时函数中的代码能够执行,也就是在对象指针的支持下实现的。前面我们说了,对象指针只有在对象创建之后才有的,我们在类里声明,类都没有声明完,对象又如何存在呢?那么这样我们还如何定义类,如何定义成员函数呢?然而有了this指针,我们也就依托于对象指针,成员函数里调用其他成员函数和变量也就都通过指针,也就有了合理的依据。而this指针在对象创建之后,就可以指向当前对象,然后实现各种成员变量和成员函数的访问了。this->PFUN_CLASS();
但是这样写的话,是不是和指针直接调用成员函数语法一样了,这样也就提示不存在成员函数PFUN_CLASS了。既然PFUN_CLASS是成员函数指针,那我们对指针取值一下,这样得到函数名,然后用this指针来操作,不就符合了普通的成员函数调用的规则了嘛。当然我们需要注意优先级,所以先将左边一部分括起来,就是这样的:(this->*PFUN_CLASS)();
这样的写法再也不会和之前的语法撞上了。对,就这么写了。看起来别扭,但是意义推理都说的通呀。
struct C {
void func1(){}
void func2(){}
};
typedef void (C::*pFunc)();
int main() {
C c;
pFunc funcArray[2] = {&C::func1, &C::func2};
(funcArray[0])(); // C2064
(c.*funcArray[0])(); // OK - function called in instance context
}
所以,对于类内的非静态成员函数的函数指针的使用,在函数指针声明时要加类作用域、在赋值传参的时候要加取值地址符号,然后在函数调用的时候,需要显式的使用this指针和*取值操作符。这样也就万事大吉了。而对于静态函数指针(普通C函数指针和类静态函数指针),就简单的不用说了。void (A::*PFUN_CLASS)();
这样的定义,就是定义一个指针变量,即函数指针变量。指针如何使用,我们已经说了。typedef void (A::*PFUN_CLASS)();
而这样的,在前面加一个typedef,就是定义了一个类型,即函数指针类型。我们可以用类型再去声明一个函数指针变量,而不是直接拿类型当做指针变量使用哦。也就是加了typedef而已,你只要知道,typedef是重定义类型的,那么后面的自然就是类型咯。这样是不是和函数指针变量的定义一下就区分开来了。相关资讯