Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

lavi

c++ virtual table - right

This topic is 5831 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
"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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

#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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
By the way lavi, you just use a single jump. The overhead is an additional indirection when fetching the address, but no second jump.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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:


  
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?");
};

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!