继我的问题:Detect the the vtable offset of a specific virtual function (using Visual C++):
假设:
struct A
{
virtual void a() {}
virtual void b() {}
virtual void c() {}
};
如何在Visual C ++中编写函数(可能是非可移植的),例如:
int x = GetVtableIndex(&A::a); //returns 0
int x = GetVtableIndex(&A::b); //returns 1
int x = GetVtableIndex(&A::c); //returns 2
我想要这样做的原因是在链接问题中。
答案 0 :(得分:7)
受到imre答案的启发,如果您只是想知道vtable的总大小;即,有多少虚拟功能,这可能有效。此方法不会实例化该类。
template <typename T>
int VTableSize()
{
class VTableCounter
{
public:
virtual int Get1() { return 0; }
virtual int Get2() { return 1; }
virtual int Get3() { return 2; }
// ... 994 more ...
virtual int Get998() { return 997; }
virtual int Get999() { return 998; }
virtual int Get1000() { return 999; }
};
class A : public T
{
public:
virtual int LastVirtual() {return -1;}
};
VTableCounter vt;
return reinterpret_cast<A*>(&vt)->LastVirtual();
}
注意我没有使用Boost.PP,因为我可以告诉它限制为256。您应该能够使用vim宏或其他东西来获取任意数量的虚拟内容。但是,如果使用多重或虚拟继承,它可能会给出不正确的值。
答案 1 :(得分:7)
受到imre和Ivan的回答的启发,我认为这可以完全解决:
template <class T, typename F>
int VTableIndex(F f)
{
struct VTableCounter
{
virtual int Get1() { return 1; }
virtual int Get2() { return 2; }
virtual int Get3() { return 3; }
virtual int Get4() { return 4; }
// ... more ...
} vt;
T* t = reinterpret_cast<T*>(&vt);
typedef int (T::*GetIndex)();
GetIndex getIndex = (GetIndex)f;
return (t->*getIndex)();
}
int n = VTableIndex<A>(&A::c); //returns 3
答案 2 :(得分:4)
试试这个:
#include <boost/preprocessor/repeat.hpp>
struct VtableIndexCalculator
{
#define VTIC_GET_INDEX(z, i, d) virtual int GetIndex_ ## i() { return i; }
BOOST_PP_REPEAT(128, VTIC_GET_INDEX, unused);
#undef VTIC_GET_INDEX
};
template <class C, typename F> int GetVtableIndex(C& object, F function)
{
static VtableIndexCalculator calculator;
static void** vtable_new = *(void***)&calculator;
void*** pvptr = (void***)&object;
void** vtable_old = *pvptr;
*pvptr = vtable_new;
typedef int (C::*GetIndex)();
GetIndex getIndex = (GetIndex)function;
int index = (object.*getIndex)();
*pvptr = vtable_old;
return index;
}
缺点是要获取C :: F函数的vtable索引,需要一个C的实际实例(这个版本需要是一个非const实例,但我认为可以创建一个const版本),因此它不适用于抽象类。
另外,我刚做了一些快速测试,它似乎到目前为止工作,但我不确定它是否总是这样(可能取决于C使用什么类型的继承,如果它有任何继承的虚拟功能或所有虚拟在C中声明,甚至是否启用增量链接),所以要小心。
这是做什么的:
object
)和指向成员函数的指针(称为function
),则获取一个实例。 object
的vptr,使其指向VtableIndexCalculator的vtable。 function
转换为与VtableIndexCalculator中的GetIndex()函数的签名匹配的不同函数指针。 object
上调用生成的指针指向成员。