Reputation: 337
Is it possible (and how) to obtain the index of a virtual function in the virtual method table?
class A
{
virtual void foo();
}
I know foo
is the first (0) item in the virtual method table
However can I have foo
and get 0?
Upvotes: 1
Views: 3046
Reputation: 170084
You seem to want to do virtual dispatch in a general fashion, knowing only the functions signature, and getting that function reference in some other fashion.
While that pursuit may have merit, your question conflates it with an implementation detail (the vtable), which is not guaranteed by the C++ standard.
Fortunately for you, the standard offers a way to call a member function without knowing its name, and it even respects virtual dispatch. It's a simple pointer to member (which you can store and copy). You'd use it like this:
#include <iostream>
struct A
{
virtual void foo() { std::cout << "A::foo\n"; }
};
struct AA : A
{
virtual void foo() { std::cout << "AA::foo\n"; }
};
struct AAA : AA
{
virtual void foo() { std::cout << "AAA::foo\n"; }
};
void bar (A& a, void (A::* pMem)())
{
(a.*pMem)();
}
int main() {
A a;
AA aa;
AAA aaa;
bar (a, &A::foo);
bar (aa, &A::foo);
bar (aaa, &A::foo);
return 0;
}
Upvotes: 0
Reputation: 280
Ideally, we can loop the functions address and compare the specified function's address, i wrote following code in g++, which could output the index of virtual function.
#include <iostream>
#include <stdio.h>
using namespace std;
class test {
public:
virtual void foo() {
cout << "foo" << endl;
}
virtual void goo() {
cout << "goo" << endl;
}
virtual void hoo() {
cout << "hoo" << endl;
}
};
int find_function_index(test* p, void* f) {
for(int i = 0; i < 3; ++i) {
void* tmp = (void*)*((long*)*(int*)(p)+i);
if(tmp == f)
return i;
}
return -1;
}
int main() {
test* p = new test();
void* f1 = reinterpret_cast<void*>(&test::foo);
cout << "foo: " << find_function_index(p, f1) << endl;
void* f2 = reinterpret_cast<void*>(&test::goo);
cout << "goo: " << find_function_index(p, f2) << endl;
void* f3 = reinterpret_cast<void*>(&test::hoo);
cout << "hoo: " << find_function_index(p, f3) << endl;
}
The following pic is the address of test::goo and the value of f2 (which is store the correct address of test::goo)
Upvotes: 0
Reputation: 50550
As I said in the comments, I suspect it's implementation defined an implementation detail (thanks to @SteveJessop for having pointed the right terms out in the comments to the answer) and depends on the ABI, so (theoretically) it is not possible in a portable way.
As an example of a known ABI definition, see here (Itanium C++ ABI).
In other terms, that's a jargon term in the C++ standard and means - the implementation must document it.
Moreover, as @n.m. mentioned in the comments to the question, the standard doesn't contain anything like a vtable, so hardly is it ruled explicitly.
Implementations are free to use them or not, and if they use them they're free to provide a supported means for user code to access them or not.
That said, again: there is not an explicit, portable way to do that.
Upvotes: 1
Reputation: 71989
Even though vtables happen to be the way most (probably all) C++ implementations implement virtual function dispatch, there's no guarantee of them even existing in the standard, much less that they're in a particular order.
In other words, the only way to know is to take your particular compiler, find out how it arranges the vtable, and then follow the same algorithm based on the class layout to find the index for the function you're interested in.
Or otherwise use incredibly platform-specific hacks to get the actual address of the member function, find the vtable in memory, and search for the address inside.
But either way, such information is specific to one platform and compiler, possibly even compiler version, depending on the ABI guarantees of that particular compiler.
As a side note, both GCC and MSVC++ have documented layout algorithms for their vtable, and documented algorithms for where the vptr sits in an object. For GCC, the documentation is the Common C++ ABI (a.k.a. Itanium C++ ABI). For MSVC++, I don't know where the documentation is or if it exists directly, but the compiler guarantees that at least classes without data members are laid out to be compatible with the COM ABI.
Upvotes: 1