BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #94465同步于 2017/2/12
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

void*类型的指针

liuyehcf
2017/2/12镜像同步15 回复
void* 类型的指针无法保存非静态成员函数的地址 ```C class A{ public: void f1(){} static void f2(){} }; int main(){ void *p1=&A::f1;//报错 void *p2=&A::f2; } ``` 为什么void*类型的指针无法保存非静态成员函数的地址? 可不可以定义这样一种函数指针类型:使得它可以指向任意类型的函数
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
Mrsuyi机器人#1 · 2017/2/12
A::f1有一个隐含的参数,类型是A*,也就是你在f1的定义中可以直接使用的this关键字 如果声明成 void f1() const {} 那么对应的参数就是const A* 指向任意函数的指针貌似不行,但是如果你不怕死可以全部都用void*加类型强转。。
liuyehcf机器人#2 · 2017/2/12
非常感谢,但是编译器好像禁止我强制类型转换,(void*)和static_cast<void*>()好像都不行 【 在 Mrsuyi 的大作中提到: 】 : A::f1有一个隐含的参数,类型是A*,也就是你在f1的定义中可以直接使用的this关键字 : 如果声明成 void f1() const {} 那么对应的参数就是const A* : 指向任意函数的指针貌似不行,但是如果你不怕死可以全部都用void*加类型强转。。
mo1028496361机器人#3 · 2017/2/12
1、类定义时并不会分配内存,在实例化对象时才回所需的分配内存,没有分配内存就自然就没有地址了,静态成员函数在程序一开始就会分配内存 2、指向不同函数类型的指针间不存在转换规则
liuyehcf机器人#4 · 2017/2/12
非静态成员函数的地址也是一开始就分配的,并不需要创建实例 【 在 mo1028496361 的大作中提到: 】 : 1、类定义时并不会分配内存,在实例化对象时才回所需的分配内存,没有分配内存就自然就没有地址了,静态成员函数在程序一开始就会分配内存 : 2、指向不同函数类型的指针间不存在转换规则
specops机器人#5 · 2017/2/12
所以p1报错p2正常 【 在 liuyehcf (安静的牛皮糖) 的大作中提到: 】 : 非静态成员函数的地址也是一开始就分配的,并不需要创建实例
liuyehcf机器人#6 · 2017/2/12
报错的原因是不能赋值给void*,改成auto p1=&A::f1; 就没问题了 【 在 specops 的大作中提到: 】 : 所以p1报错p2正常
aromazyl机器人#7 · 2017/2/12
&A::f1的语义和常规指针不一样了吧。我记得深入探索xx模型书里面说,这个指的是偏移。可以用printf打印出来看看。
Mrsuyi机器人#8 · 2017/2/12
【 在 liuyehcf 的大作中提到: 】 : 非常感谢,但是编译器好像禁止我强制类型转换,(void*)和static_cast<void*>()好像都不行 呃,是这样,全局函数和类的static成员函数是一样的,可以直接取到地址,然后就可以随意地转类型调用了 但是对类的非static函数取地址会取到一个“类成员函数指针”,这个东西跟普通指针不太一样,你可以sizeof看一下差别。不过内容应该都会包含内存地址,所有你定义的函数在运行时一定是有内存地址的,只不过直接(void*)&A::f1是被编译器禁掉了 不过我搜到了一个猥琐的办法。。。 union un { void* addr; void(A::*f)(); } u; u.f = &A::f1; 然后你就可以用u.addr了 void(A::*ptr)(); memcpy(&ptr, &u.addr, sizeof(ptr)); ((A*)nullptr->*ptr)(); // 这个是“类成员函数指针”的调用方式,因为A::f1的定义没有用到this,所以这里就算在nullptr身上调用A::f1也不会崩溃
liuyehcf机器人#9 · 2017/2/12
太谢谢了~,union第一次见到呢,涨知识了 我想把成员函数的指针赋给void*的意图是想通过一个map来实现string到成员函数的映射,从而实现一下简单的反射,不知道这个有没有什么办法可以实现 【 在 Mrsuyi 的大作中提到: 】 : : 呃,是这样,全局函数和类的static成员函数是一样的,可以直接取到地址,然后就可以随意地转类型调用了 : 但是对类的非static函数取地址会取到一个“类成员函数指针”,这个东西跟普通指针不太一样,你可以sizeof看一下差别。不过内容应该都会包含内存地址,所有你定义的函数在运行时一定是有内存地址的,只不过直接(void*)&A::f1是被编译器禁掉了 : ...................