c++ virtual table - right
class A {
public:
virtual void Test() {cout<<"A\n";}
};
class Bublic A {
public:
virtual void Test() {cout<<"B\n";}
};
int main()
{
A* pa = new B;
pa->Test();
return 0;
}
Here I''m using 2 jumps :first to the virtual table and then to the right
function (Test() for class B).
Question:
How can I call the function directly :
How can I access the virtual table by myself take the function address from there
and call the function ??
Thank you.
"How can I call the function directly :
How can I access the virtual table by myself take the function address from there
and call the function ??"
That would be a clear example of anti-C++. Inline the function if the speed is a concern.
Forever trusting who we are
And nothing else matters - Metallica
How can I access the virtual table by myself take the function address from there
and call the function ??"
That would be a clear example of anti-C++. Inline the function if the speed is a concern.
Forever trusting who we are
And nothing else matters - Metallica
simple: take the function pointer and you have it, virtual without the keyword is something like:
void TestA(){cout<<"A\n";};
void TestB(){cout<<"B\n";};
class A{
void (*Test)();
public:
A(void (*func_ptr)()= TestA) : Test(func_ptr) {};
};
class B : public A{
B() : A(TestB) {};
};
and you can simply call the func (only if it is const) via A::Test(), and non const ? maybe A::Test((A*)0) ? dont know, never tried ...
T2k
[edited by - T2k on June 4, 2002 8:08:37 AM]
void TestA(){cout<<"A\n";};
void TestB(){cout<<"B\n";};
class A{
void (*Test)();
public:
A(void (*func_ptr)()= TestA) : Test(func_ptr) {};
};
class B : public A{
B() : A(TestB) {};
};
and you can simply call the func (only if it is const) via A::Test(), and non const ? maybe A::Test((A*)0) ? dont know, never tried ...
T2k
[edited by - T2k on June 4, 2002 8:08:37 AM]
Here is an example of a HACK that calls a private member function of a class, circumventing the protection mechanism by using the á priori knowledge about the binary representation of classes for VC++ .
Side note: I did not write this code.
Forever trusting who we are
And nothing else matters - Metallica
Side note: I did not write this code.
#include <iostream> #include <iomanip> using namespace std; class CA { protected: virtual void f1() { cout << "CA::f1()" << endl; } }; class CB : public CA { protected: virtual void f1() { cout << "CA::f2()" << endl; } }; union INTANDPTR { int i; void (CA::*f1p)(); }; int main(int argc, char* argv[]) { CA * pCB = new CB; //pCB->f1(); void (CA::*f1p)(); int ** iObject = ((int**)pCB); int * pVtbl = (iObject[0]); int * pVtblEntry = &pVtbl[0]; INTANDPTR iptr; iptr.i = pVtblEntry[0]; f1p = iptr.f1p; (pCB->*f1p)(); return 0; }
Forever trusting who we are
And nothing else matters - Metallica
That is a sick hack indeed. Why do this at all? The overhead for a virtual function call is not significant enough to warrant that kind of, er..., goo. Not to mention it''s absolutely non-portable to other compilers and might not even port to other versions of VC.
By the way lavi, you just use a single jump. The overhead is an additional indirection when fetching the address, but no second jump.
quote:Original post by Kippesoep
That is a sick hack indeed. Why do this at all? The overhead for a virtual function call is not significant enough to warrant that kind of, er..., goo. Not to mention it''s absolutely non-portable to other compilers and might not even port to other versions of VC.
Yes, I fully agree, that is an ugly hack. I stated that pretty clearly, as you can see in my prev. post. The only reason why I saved it is that I found it somehow interesting - you know, if something is ugly enough it begins to become beautifull .
The only use I see for it is that writing/reading things like that may enhance your understanding of classes and the representation a compiler might use for them.
Forever trusting who we are
And nothing else matters - Metallica
If you want to call a virtual function directly, odds are you're abusing inheritence or using it needlessly.
[edited by - Stoffel on June 4, 2002 12:54:44 PM]
[edited by - Stoffel on June 4, 2002 12:54:44 PM]
Here''s how to find an class''s vtable. First, you create an object of the class. Then you cast that object''s this pointer to a void**. Then dereference once. Viola! A pointer to the class''s vtable! I''ve tried this method and it works as long as you have the objects real this pointer. All objects store a pointer to their vtable as the first member of the object in memory. But the compiler makes it seem like that pointer isn''t there. Also, if you ever bother to look through your compiler''s docs you''ll find that a method is just a regular function that takes an implicit first parameter, the this pointer. Hence the following code works:
It works because of the rules I just explained. They go, no matter what compiler you work with. I know because it works with my classes made in C++ Builder AND with COM objects that were undoubtedly made in Visual C++. Also, the vtable of a class stays instantiated even if there are no objects of that class. I hope you can put this knowledge to good use.
void Signature(void* Pointer)
{
PObject(Pointer)->ShowMessage("Why do we need so many pointers?");
};
class TestA{virtual void Test() {cout<<"Is TestA\n";};};class TestB: public TestA{virtual void Test() {cout<<"Is TestB\n";};};typedef void(*PTestFunc)(void* This);int main(){//Call TestA::Test() from vtable.TestA* ATest = new TestA;void* pVtblA = *((void**)ATest);PTestFunc pTest = reinterpret_cast<PTestFunc>(*((void**)pVtblA));//Prints "Is TestA".pTest(ATest);delete ATest;//Call TestB::Test() from vtable.ATest = new TestB;void* pVtblB = *((void**)ATest);pTest = reinterpret_cast<PTestFunc>(*((void**)pVtblB));//Prints "Is TestB".pTest(ATest);delete ATest;};
It works because of the rules I just explained. They go, no matter what compiler you work with. I know because it works with my classes made in C++ Builder AND with COM objects that were undoubtedly made in Visual C++. Also, the vtable of a class stays instantiated even if there are no objects of that class. I hope you can put this knowledge to good use.
void Signature(void* Pointer)
{
PObject(Pointer)->ShowMessage("Why do we need so many pointers?");
};
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement