Click here to Skip to main content
15,922,894 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi
I'm running the following C++ code of polymorphism:

C#
class Base
{
public:
    virtual void f1() {std::cout << "base f1" << std::endl;}
    void f() {std::cout << "base f" << std::endl;}
};

class Derived : public Base
{
public:
    virtual void f() {std::cout << "Derived f" << std::endl;}
};
class DDerived : public Derived
{
public:
    virtual void f() {std::cout << "DDerived f" << std::endl;}
};

C#
Base* p_base = new DDerived();
p_base->f();
Derived* p_derived = new DDerived();
p_derived->f();


and the result is:
VB
base f
DDerived f

it is expected since Base doesn't have f() in its virtual function table, and Derived should have it.

But how does it work?
Derived and DDerived should inherit the virtual function table from Base, that contains f1() and not f().

But Derived and DDerived should also have f() in their virtual function table. Do they have 2 different virtual tables?
I use Visual Studio 2008 debugger and I see only one virtual function table and it doesn't contain f().
Where is the virtual function f() located?

Thanks!
Moti
Posted

It's all there, it's the debugger that is at fault.

Try opening a memory window and locate p_derived->__vfptr and you will see all entries in the vtable.

Derived and DDerived should have two different vtables, since their second entry differs, virtual f.

The layout of the vtable is compiler dependant, but it seems all virtual functions are put in order using VC++.

You can look at the entire vtable if you add this helper variable:

void (**vt)() = *(void (***)())p_derived;


and then inspect vt,2 in a watch window.

This[^] was a similar discussion, which should have all credit for the vt trick.
 
Share this answer
 
When you write:

p_base->f();


the compiler converts it to:

Base::f( p_base );


It doesn't go anywhere near the v-table, it has no reason to - you told it f() wasn't virtual for the base class.

When you write:

p_derived->f();


the compiler converts it to something like:

p_dervived->v_table[ 1 ]( p_derived );


as f() is marked as virtual in Derived. So the moral of this lot is you have to tell the compiler when you want virtual dispatch.

Now where has the v-table gone? Well if you've declared the classes and the test code all in one translation unit the compiler can optimise the generated code to buggery provided it doesn't change the observable nature of the program. So provided the code generates the two messages correctly the compiler can remove the v-table, it doesn't need it.

Cheers,

Ash
 
Share this answer
 
Following would be a good read:

http://www.openrce.org/articles/files/jangrayhood.pdf[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900