我将带你走上黑暗而可怕的道路,前往行为不明的土地……
这里的问题是您需要调用指向成员函数的指针,而实际上没有指向成员函数的指针。你可以使用一些来自 UB 的黑魔法来完成这个任务。这个黑魔法可以让你将一个简单的整数值转换为一个完全可用的指向成员函数的指针。为此,我们可以创建一个union
...
// Magical beans. Replace with your own beans if you have them.
struct ZMyCharacter {};
// Here be dark magic!
union FunctionAddress
{
typedef void (ZMyCharacter::*MEMBER_FUNC)(D3DXVECTOR3);
FunctionAddress(uintptr_t addr) : address(reinterpret_cast<void*>(addr)) {}
MEMBER_FUNC function;
private:
void* address;
};
这种神奇的union
方法将允许您通过其构造函数从一个简单的整数值设置指向成员函数的指针......
FunctionAddress pZMyFunction(0x004A2AF0);
要使用它,您需要进行一些更改以ZMyCharacter_SetDirection_Rev
直接调用成员函数,而不是将其作为指向另一个函数的指针传递(基于您之前的问题,我假设它是一些内联汇编)...
void ZMyCharacter_SetDirection_Rev( void )
{
if( pZMyCharacter == NULL )
{
printf( "cannot set direction now\n" );
return;
}
D3DXVECTOR3 pos = D3DXVECTOR3(4.0f,2.0f,1.0f);
// directly call using pointer to member function
(pZMyCharacter->*pZMyFunction.function)( pos );
}
请记住,如果该函数是虚拟的,则您正在回避虚拟函数调度。如果是这种情况,您应该为它破坏多态性的情况做好准备。如果您想完全支持虚拟功能的分派,您将需要对虚拟表的布局进行完全逆向工程。为此,您可以做一些不使用太多黑暗魔法的更简单的事情。
// reverse engineered virutal function layour/ordering
struct ZMyCharacter
{
virtual void func1();
virtual void func2();
virtual void func3();
virtual void target_function(D3DXVECTOR3&);
virtual void func4();
};
void ZMyCharacter_SetDirection_Rev( void )
{
if( pZMyCharacter == NULL )
{
printf( "cannot set direction now\n" );
return;
}
D3DXVECTOR3 pos = D3DXVECTOR3(4.0f,2.0f,1.0f);
pZMyCharacter->target_function( pos );
}
我意识到这会改变您当前代码库的一些内容。您应该能够将代码或概念集成到您要完成的工作中。
我提到的未定义行为是关于访问工会的非活动成员。通常这被认为是不好的。