再谈C++类成员函数的指针问题
关于C++类成员函数的指针问题,CSDN已经有很多人问过了,举个例子。
class A{
public:
void a(){}
};
出问题的原因就是有人一相情愿的声明
void (*test)=&A::a //Error:Cannot convert 'void (A::*)()' to 'void (*)()'
这就出了问题,因为类A没有实例,当然成员函数void a()就没有一个确定的地址。解决的办法也比较简单:
1.把void a()声明为static。不过这是个最笨最没人愿意干的办法,class A的一
般成员都不能访问了,那把void a()放在class A里面干什么呢?一般情况下不可取。
2.把指针声明改成void (A::*)test,那也就轻松过关。不过调用的时候却得找一个实例才能嫁得出去。
似乎问题已经完了,却还有一个问题。如果给出了实例
A aa;
又当如何呢?
CSDN有不少回答是这样的:
test=&(aa.a)甚至于test=aa.a
可是这样编译能通过吗?至少我没做到,诸位有什么办法。
我们继续。有人骂过这样用的人,真是无聊。其实这种用法相当普遍。在Borland
的C++ Builder里,比如一个TButton,它的OnClick就是一个函数指针,往往是指
向TForm的子类的一个成员函数。这时候上面的方法2又出了问题。方法2是预先知
道了类名才声明的函数指针,而我们的Form都是继承至TForm,类名根本就不知道
,而Borland却做到了这一点。激动地想看看Borland的高超水平,仔细看过,大
失所望。Borland增加了一个关键词__closure,以此声明的函数指针可以自动绑
定一个实例,调用就轻而易举了。
void (__closure *test)=aa.a;
test();
可怜我们这些遵守ANSI C++的却没办法改变编译器。
要预先得知还没有编出来的类的名字,我们的手段当然是template。借助模板,
这个问题也可以得到解决。可惜模板只对函数和类而言,为一个指针再来打造一
个类,是不是太浪费了一点?而且一但确定了,我们却不能再随心所欲地更改这
个指针,我们只能让这个指针在这个类里兜圈子,还要传递实例的参数,麻烦!
那我们怎么才能做到像Borland一样的效果呢?CSDN里有人是这么说的
“在函数入口处通过访问堆栈得到函数入口地址”
我的水平还不到这一步,我做不到。我也不知道这样干对于BC和VC是否同样有效
,但我相信C++能有一个圆满的答复,希望诸位能加入讨论一下。