C++ 无法在类型转换为void的对象上调用成员函数指针*

C++ 无法在类型转换为void的对象上调用成员函数指针*,c++,pointers,function-pointers,C++,Pointers,Function Pointers,所以我想使用成员函数指针的原因就是从一个不知道对象类型并且所有对象都被视为void*对象的位置调用函数。但我不能这样做,即使从理性上看,函数指针指向子例程的地址,因此对象的类型应该是无关紧要的。我的假设是,系统所要做的就是将“this”指针设置为调用成员函数指针的对象。下面是我的代码。我怎样才能实现我想要的 class C2 { public: int y; void SetValue(int); }; void C2::SetValue(int k) {

所以我想使用成员函数指针的原因就是从一个不知道对象类型并且所有对象都被视为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);
}
C2类
{
公众:
int-y;
无效设置值(int);
};
无效C2::设置值(整数k)
{

cout解决您的问题的简单方法是将
static\u cast
您的
Ob2
转换为正确的类型,因为您需要知道函数所属的类:

(static_cast<C2*>(Ob2)->*f)(10);
(静态铸造(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);
模板
Ret callMemPtr(Ret(C::*fun)(参数…,void*obj,参数和参数)
{
返回(静态施法(obj)->*fun)(标准:向前(args)…);
}
//用法
callMemPtr(f,Ob2,10);
然而,这似乎是一种奇怪的方法。您最好使用继承或某种形式的类型擦除

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

尽管对于指向独立函数的指针以及指向
静态
成员函数的指针来说肯定是这样,但指向实例成员函数的指针是不同的。指向成员函数的指针可能是数据结构,而不是单个指针,因为它需要支持虚拟分派

考虑以下代码片段:

#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;
}
#包括
结构基{
虚拟void foo()=0;
};
结构派生:公共基{
虚拟void foo(){

我不知道你为什么想要这个,但你可以去yolo,像这样做:

#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;
}
#包括
课堂测试
{
公众:
test(){}
无效回声(int x)
{

std::cout在不知道成员所属类型的情况下,如何拥有成员函数指针?在您的示例中,
f
的类型为
void(C2::*)(int)
,所以您知道必须在
C2
的实例上调用它。您想要从
void
隐式转换到您的类型吗?!但是我已经将函数指针设置为指向特定类的成员函数,该类是C2。因此,不管函数指针在哪个对象上,我都希望调用函数时,函数应该被执行,听起来可能需要使用继承和虚函数。<代码> Value*/Cord>不应该是在现代C++中被忽略的东西。@ rAKS,不管调用函数指针的对象,函数应该被执行。这是违背C++的类型系统的。C++是强类型的,静态类型的:如果你有一个函数,它期望int是一个参数,你只能用int调用它。同样的,对于成员函数指针,编译器阻止你用“<代码>空洞*>代码>调用成员函数,因为这不是类型化的。(您的对象可能不是一个
C2
),因此您必须通过使用强制转换明确地“绕过”类型系统:
(static_cast(Ob2)->*f)(10);
那么,当我们说f=&C::SetValue,而f声明为void(C2:*f)(int)时,变量“f”实际指向什么;@Raks成员函数指针的实际结构是特定于编译器的。编译器决定需要在其中存储什么,以便能够确定调用什么。例如,如果虚拟分派是使用vtables实现的,则此结构可以在存储实际指针的vtable中包含偏移量。但是如果指针不是一个虚拟函数,那么甚至不需要虚拟表查找。我认为重要的是将“this”指针设置为调用该函数的对象。@Raks Here
MemFn f(&Base::foo);
编译器知道该函数是
virtual
。然而,Here
(d.*f)()
它不知道
f
是否为
virtual
,它必须准备好处理这两种可能性。@Raks因为设置指针的位置和使用指针的位置可能在不同的转换单位中。指针从设置时起必须是自给自足的。在调用点t编译器不知道在指针中设置了什么特定函数(否则,指针将毫无用处)。不过,它需要有完整的信息才能进行调用。