虚拟功能未在vptr中列出

时间:2012-02-06 20:09:10

标签: c++ visual-studio-2008

vptr索引应显示所有虚拟功能,但在我的情况下,只显示3个虚拟功能中的2个。

我提供完整的代码和截图如下: -

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();

}

Manager类有两个虚拟函数,pay和Rank,但只有pay显示在vptr中。

有人可以告诉我,为什么Rank不显示,即使它的虚函数。

我在Windows 7 64位上使用Visual Studio 2008和最新更新。

enter image description here

JuniorManager Debugger屏幕截图

它也没有显示虚拟功能。请看下面的图片。

enter image description here

5 个答案:

答案 0 :(得分:2)

如果您将该类检查为Employee,由于该类没有Rank(),它将不会在vtable中显示Rank()。您的屏幕截图显示了Employee类的内容。

  

“是的,调试器没有足够的类型信息来判断   阵列有多长。所以它只显示第一个元素,除非   覆盖“。

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

答案 1 :(得分:1)

也许这是因为Manager是从Employee派生的,但Employee没有Rank方法。因此,当Manager对象调用Rank()时,它永远不需要在虚拟表中。 我打赌,如果你实例化一个JuniorManager排名将在vtbl。

有关更多说明,请查看Does C++ virtual function call on derived object go through vtable?但我相信这是正确的理由。

答案 2 :(得分:1)

我相信这是因为在Manager继承链中没有可能的Rank函数覆盖,即使它是虚拟的。换句话说,我认为你的类必须知道可重写的虚函数在哪里正确地调度函数调用,这意味着实现必须存储指向虚函数的指针。如果没有人可以覆盖这些函数,那么调度中没有歧义,没有理由在vtable中保留另一个指针。

你应该能够通过与JuniorManager实例完全相同的练习来验证:因为我们需要在JuniorManager实例中维护一个指向Manager的Rank函数的指针,因为我们有一个覆盖Rank函数,我们应该在JuniorManager的vtable中看到虚拟指针。

现在我很好奇。你能帮我们检查一下并报告回来吗?

答案 3 :(得分:0)

我认为我们在这里看到的是一个奇怪的Visual Studio怪癖,我无法解释。

我将代码复制到Visual Studio中以查看发生了什么,我甚至尝试添加:

JuniorManager *p1 = new JuniorManager();

p1显示为JuniorManager,它是Manager的子类,是Employee的子类。

在所有情况下,调试器都完全了解指针变量的确切静态类型指向的对象的确切动态类型以及vtable的确切类型和确切的类型vtable中的条目。但是,vtable仅在调试器中作为基类(Employee)的一部分可见,并且由于某种原因,仅显示基类的已知条目。

如果要显示其余条目,那将会更酷。

答案 4 :(得分:0)

切换链接器属性链接器 - >优化 - >参考/ OPT:NOREF。 Visual Studio删除对未使用(未定义)的函数的引用。使用此开关链接器不会删除这些引用。