不能在类型转换为void *的对象上调用成员函数指针

Cannot call a member function pointer on a object typecasted as void *

本文关键字:调用 成员 函数 指针 对象 类型转换 void 不能      更新时间:2023-10-16

所以我想使用成员函数指针的原因是调用函数从一个地方,对象的类型是未知的,其中所有的对象被视为void *对象。但我不能这样做,即使理性地似乎函数指针指向子程序的地址,因此对象的类型应该是无关紧要的。我的假设是,系统所要做的就是将"this"指针设置为调用成员函数指针的对象。下面是我的代码。我怎样才能实现我想要的

class C2
{
    public:
       int y;
       void SetValue(int);
};
void C2::SetValue(int k)
{
    cout<<"Setting Value inside C2"<<endl;
    y=k;
}
int main()
{
    void (C2::*f)(int);
    C2 *Ob=new C2();
    void *Ob2=(void *)Ob;
    f = &C2::SetValue;
    ((Ob2)->*f)(10);
}

这段代码甚至不能用vc++编译器编译,错误为

错误C2296: '->*':非法,左操作数类型为'void *'

好吧,你的问题的简单解决方案是static_cast你的Ob2到正确的类型,因为你需要知道函数属于的类:

(static_cast<C2*>(Ob2)->*f)(10);

你可以用模板自动完成:

template <typename Ret, class C, typename... Params, typename... Args>
Ret callMemPtr (Ret (C::*fun) (Params...), void* obj, Args&&... args)
{
    return (static_cast<C*>(obj)->*fun)(std::forward<Args>(args)...);   
}
//usage
callMemPtr(f,Ob2,10);

然而,这似乎是一种奇怪的方法。您最好使用继承或某种形式的类型擦除。

按理说,函数指针似乎指向子程序的地址,因此对象的类型应该是无关紧要的。

虽然指向独立函数的指针和指向static成员函数的指针都是正确的,但是指向实例成员函数的指针是不同的。指向成员函数的指针可以是一个数据结构,而不是单个指针,因为它需要支持虚拟分派。

考虑以下代码片段:

#include <iostream>
struct Base {
    virtual void foo() = 0;
};
struct Derived : public Base {
    virtual void foo() {
        std::cout << "Hello" << std::endl;
    }
};
typedef void (Base::*MemFn)();
int main() {
    Derived d;
    MemFn f(&Base::foo);
    (d.*f)();
    return 0;
}

上面,f是指向Base::foo的指针,但是Derived::foo被调用了(demo)。

这就是为什么不能将函数指针转换为void*的原因之一。Void指针是指向数据的指针,而函数指针是指向代码的指针。

我不知道你为什么要这样做,但是你可以这样做:

#include <iostream>
class test
{
public:
    test(){}
    void echo(int x)
    {
        std::cout << "I'm being called: " << x << std::endl;
    }
};
int main()
{
    test t;
    (t.*((void(test::*)(int))&test::echo))(10);
    std::cin.get();
    return 0;
}