返回信息流void* 类型的指针无法保存非静态成员函数的地址
```C
class A{
public:
void f1(){}
static void f2(){}
};
int main(){
void *p1=&A::f1;//报错
void *p2=&A::f2;
}
```
为什么void*类型的指针无法保存非静态成员函数的地址?
可不可以定义这样一种函数指针类型:使得它可以指向任意类型的函数
这是一条镜像帖。来源:北邮人论坛 / cpp / #94465同步于 2017/2/12
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
void*类型的指针
liuyehcf
2017/2/12镜像同步15 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
A::f1有一个隐含的参数,类型是A*,也就是你在f1的定义中可以直接使用的this关键字
如果声明成 void f1() const {} 那么对应的参数就是const A*
指向任意函数的指针貌似不行,但是如果你不怕死可以全部都用void*加类型强转。。
非常感谢,但是编译器好像禁止我强制类型转换,(void*)和static_cast<void*>()好像都不行
【 在 Mrsuyi 的大作中提到: 】
: A::f1有一个隐含的参数,类型是A*,也就是你在f1的定义中可以直接使用的this关键字
: 如果声明成 void f1() const {} 那么对应的参数就是const A*
: 指向任意函数的指针貌似不行,但是如果你不怕死可以全部都用void*加类型强转。。
1、类定义时并不会分配内存,在实例化对象时才回所需的分配内存,没有分配内存就自然就没有地址了,静态成员函数在程序一开始就会分配内存
2、指向不同函数类型的指针间不存在转换规则
非静态成员函数的地址也是一开始就分配的,并不需要创建实例
【 在 mo1028496361 的大作中提到: 】
: 1、类定义时并不会分配内存,在实例化对象时才回所需的分配内存,没有分配内存就自然就没有地址了,静态成员函数在程序一开始就会分配内存
: 2、指向不同函数类型的指针间不存在转换规则
报错的原因是不能赋值给void*,改成auto p1=&A::f1; 就没问题了
【 在 specops 的大作中提到: 】
: 所以p1报错p2正常
【 在 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也不会崩溃
太谢谢了~,union第一次见到呢,涨知识了
我想把成员函数的指针赋给void*的意图是想通过一个map来实现string到成员函数的映射,从而实现一下简单的反射,不知道这个有没有什么办法可以实现
【 在 Mrsuyi 的大作中提到: 】
:
: 呃,是这样,全局函数和类的static成员函数是一样的,可以直接取到地址,然后就可以随意地转类型调用了
: 但是对类的非static函数取地址会取到一个“类成员函数指针”,这个东西跟普通指针不太一样,你可以sizeof看一下差别。不过内容应该都会包含内存地址,所有你定义的函数在运行时一定是有内存地址的,只不过直接(void*)&A::f1是被编译器禁掉了
: ...................