0

我需要在我的其他代码中验证虚拟成员函数的代码。那么如何获得指向正确代码的指针呢?

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 声明,如果你明白我的意思的话。

4

1 回答 1

0

这是我破解的一些代码,它(在 g++ 4.6.3 中)似乎给出了预期的结果。

但是,在我仅仅因为我试图解决一个无法解决的问题而被否决之前,这绝对依赖于“未定义的行为”。由于该标准甚至没有涉及虚拟方法应该如何实现与 vptr、vtable 等有关,因此如果不知道编译器做了什么,你就无法实际实现它——当然还有新版本,即使在小版本中,或者使用编译器的不同编译选项也可能会改变这一点(例如,调试模式与发布模式可能不同 - 但这会使调试和发布或混合使用新旧编译器编译的代码变得困难)

#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;
}
于 2013-07-02T11:24:58.663 回答