我需要在其他代码中验证虚拟成员函数的代码。那么如何获得指向正确代码的指针?
class MyInterface {
public:
virtual void VirtualMethod() = 0;
};
class MyImplementation : public MyInterface {
private:
int m_value;
public:
MyImplementation() : m_value(0) { }
virtual void VirtualMethod() {
m_value = 1;
}
};
void main(int argc, char* argv[])
{
MyInterface* pInterface = new MyImplementation();
// In my real code on the following line, we do not have access to the declaration of MyImplementation
unsigned int* pFunctionPointer = (unsigned int*)pInterface->VirtualMethod;
// Now we want to access the compiled code of MyImplementation::VirtualMethod.
printf("0x%08x\n", *pFunctionPointer);
}
在我的实际代码中,如果你让我漂移,我根本无法从“main”函数访问MyImplementation声明。
答案 0 :(得分:0)
这是我破解的一些代码,(在g ++ 4.6.3中)似乎给出了预期的结果。
然而,在我投票之前,仅仅是因为我试图解决一个无法解决的问题,这绝对是依赖于“未定义的行为”。由于标准甚至没有涉及如何在vptr,vtable等方面实现虚拟方法,所以在没有知道编译器的作用的情况下你无法实际实现它 - 当然,新版本,即使是在次要修订中,或者使用编译器的不同编译选项可能会改变这种情况(例如,调试模式与发布模式可能会有所不同 - 但这会使混合调试和发布或混合使用新旧编译器编译的代码变得困难)< / p>
#include <iostream>
using namespace std;
class A
{
public:
virtual void f();
};
class A2
{
public:
virtual void g();
};
class B: public A, public A2
{
public:
virtual void f();
virtual void g();
};
void print_my_addr(const char *name)
{
cout << "Address of " << name << "=" <<
__builtin_return_address (0) << endl;
}
void A::f()
{
print_my_addr(__FUNCTION__);
}
void A2::g()
{
print_my_addr(__FUNCTION__);
}
void B::f()
{
print_my_addr(__FUNCTION__);
}
void B::g()
{
print_my_addr(__FUNCTION__);
}
// p: pointer to a class object to inspect.
// base_number: which base-class to inspect. 0 = first baseclass
// func_no: function number within the baseclass.
// returns the address as a intptr_t
intptr_t findvirt(A *p, int base_number, int func_no)
{
intptr_t **vptr = reinterpret_cast<intptr_t**>(p);
intptr_t *vtable = vptr[base_number];
return vtable[func_no];
}
int main()
{
A a;
B b;
cout << hex << "Address of A::f()" << findvirt(&a, 0, 0) << endl;
a.f();
cout << hex << "Address of B::f()" << findvirt(&b, 0, 0) << endl;
b.f();
cout << hex << "Address of B::g()" << findvirt(&b, 1, 0) << endl;
}