6

The vptr index should display all the virtual functions, but in my case only 2 out of the 3 virtual functions are being displayed.

I am providing the complete code and the screenshots below :-

ClassHeader.h

#include <iostream>
using namespace std;

// Employee Class

class Employee
{
  public :
int salary ;
Employee(){cout << "Inside CTOR" << endl;}

virtual ~Employee() {cout << "Inside DTOR" << endl;}

virtual void pay(){cout << "Employee" << endl;}
};

// Manager Class

class Manager : public Employee
{
   public :

virtual void pay(){cout<< "Manager pay" << endl;}
virtual void Rank(){cout << "Manager Rank" << endl;}
};

// JuniorManager Class
class JuniorManager : public Manager
{
   public :

virtual void pay(){cout<< "JuniorManager pay" << endl;}
virtual void Rank(){cout << "JuniorManager Rank" << endl;}
};

Main.cpp

#include "ClassHeader.h"

void main()
{
    Manager *p = new Manager();

p->pay();
p->Rank();

p = new JuniorManager();
p->Rank();

Employee *pE = dynamic_cast<Employee*>(p);
pE->pay();

}

The Manager class has two virtual functions, pay and Rank, but only pay shows up in the vptr.

Can somebody please tell me, why Rank does not show up , even though its virtual function.

I am using Visual Studio 2008 , and with the latest updates, on Windows 7 64 bit.

enter image description here

JuniorManager Debugger Screenshot

It does not show the virtual functions either. Please see the image below.

enter image description here

Sujay Ghosh
  • 2,828
  • 8
  • 30
  • 47

5 Answers5

2

If you inspect the class as an Employee, since that class does not have Rank(), it will not show the Rank() in the vtable. Your screenshot shows the contents of Employee class.

"Yup, the debugger doesn't have sufficient type information to tell how long the array is. So it only displays the first element unless overridden."

http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/23d4e48e-520e-45b4-8c2f-65c11946d75d

perreal
  • 94,503
  • 21
  • 155
  • 181
  • 2
    I am declaring a pointer to a Manager , not to an Employee. Please see the complete code. – Sujay Ghosh Feb 06 '12 at 20:14
  • But the inspector window shows the Employee class. At least the contents of the table is correct in that sense. – perreal Feb 06 '12 at 20:17
  • Is this true? As I understand it, generally, each instance has only one vtable, which is merged down from its inheritance chain - that's why we see `const Manager::'vftable'` and not `const Employee::'vftable'`. I'm not a Visual Studio guru, but would it simultaneously hide virtual functions while showing the correct type? – Matt Feb 06 '12 at 20:17
  • 1
    @SujayGhosh, you've declared `Manager`, but inspecting its base `Employee` – Lol4t0 Feb 06 '12 at 20:18
  • However as perreal suggested, the Visual Studio lists you the `Employee` part of your object. – valdo Feb 06 '12 at 20:19
  • @Matt, how I understand VS downcasted `Manager` to `Employee` and showed us the result. And I'm sure, there is only a part of info, that VS shows, some info, related to `Manager` is bellow and we can't see it – Lol4t0 Feb 06 '12 at 20:20
  • The entire code is there. I also dont understand when I have declared a Manager pointer, why does VS display it as a Employee pointer in the debugger. – Sujay Ghosh Feb 06 '12 at 20:24
  • 2
    I don't think it's displaying it as an Employee pointer. The type in your screenshot is Manager. It is simply showing the contained Base class Employee Object as Employee. Look at my answer above for the reason. Your vtable doesn't have Rank as Rank for a Manager object is a direct call and there is no indirection involved. A JuniorManager however will have Rank in the vtable I'm sure. – Sid Feb 06 '12 at 20:29
  • It might be because the VS only showing base class info? Can you post a screenshot of pE when you break on the last line? May be you wont see any vtable entries in pE? – perreal Feb 06 '12 at 20:40
  • @SujayGhosh This is very odd. I think this may be a Visual Studio bug. When you call the Rank() method for JuniorManager pointer is the correct one invoked (I'm sure it is but asking to confirm) – Sid Feb 06 '12 at 20:41
  • The output is perfect, maybe you can try from you side , just copy the code and paste it. I have the book "Inside the Object Model" beside me, so we know whom to catch :-) – Sujay Ghosh Feb 06 '12 at 20:47
  • 1
    @perreal, that's an odd quote. From my experiments the debugger has enough info to fully populate the base class vtable, including the correct overridden methods from derived classes - just not, as Sujay would like, methods first declared in derived classes. – quamrana Feb 06 '12 at 21:19
  • @perreal If I go by your link, the JuniorManager should have dispayed all the virtual functions, but it displays 2 only ( please see image in the actual post ). It shall be nice if someone tries it in a different ide / OS. I only have Windows. – Sujay Ghosh Feb 07 '12 at 05:34
1

Maybe this is because Manager is deriving from Employee but Employee doesn't have a Rank method. Hence when a Manager object calls Rank() it's never going to need to be in the virtual table. I bet if you instantiate a JuniorManager Rank will be in the vtbl.

For more clarification look at Does C++ virtual function call on derived object go through vtable? but I believe this is the correct reason.

Community
  • 1
  • 1
Sid
  • 7,511
  • 2
  • 28
  • 41
1

I believe it's because there are no possible overriders of your Rank function in your Manager inheritance chain, even though it's virtual. In other words, I think your class has to know where overrideable virtual functions are to properly dispatch the function call, which means the implementation must store pointers to the virtual functions. If nobody can override the functions, there's no ambiguity in the dispatch, and no reason to keep another pointer in the vtable.

You should be able to verify by doing this exact same exercise with your JuniorManager instance: since we need to maintain a pointer to Manager's Rank function in JuniorManager instances, since we have an overriden Rank function, we should see the virtual pointer in JuniorManager's vtable.

Now I'm curious. Could you check this for us and report back?

Matt
  • 10,434
  • 1
  • 36
  • 45
0

Switch linker property Linker->Optimization->References to /OPT:NOREF. Visual Studio removes references to function that are unused (not defined). With this switch linker doesn't remove those references.

Izzy
  • 402
  • 6
  • 16
0

I think what we're seeing here is an odd quirk of Visual Studio which I can't explain.

I copied the code into Visual Studio to see what is happening and I even tried adding:

JuniorManager *p1 = new JuniorManager();

p1 is shown to be a JuniorManager which is a subclass of Manager, which is a subclass of Employee.

In all cases the debugger is fully aware of the exact static type of the pointer variables and the exact dynamic type of the objects being pointed to and the exact type of the vtable and the exact type of the entries in the vtable. However, the vtable is only visible in the debugger as part of the base class (Employee) and for some reason only the known entries for the base class are shown.

It would be much more cool if it were to show the rest of the entries also.

quamrana
  • 37,849
  • 12
  • 53
  • 71