Виртуальная функция не указана в vptr - PullRequest
6 голосов
/ 07 февраля 2012

Индекс vptr должен отображать все виртуальные функции, но в моем случае отображаются только 2 из 3 виртуальных функций.

Я предоставляю полный код и снимки экрана ниже: -

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, но в vptr отображается только pay.

Может кто-нибудь сказать мне, почему Ранг не появляется, хотя его виртуальная функция.

Я использую Visual Studio 2008 с последними обновлениями в 64-разрядной версии Windows 7.

enter image description here

Скриншот отладчика JuniorManager

Виртуальные функции также не отображаются. Пожалуйста, смотрите изображение ниже.

enter image description here

Ответы [ 5 ]

2 голосов
/ 07 февраля 2012

Если вы проверите класс как Сотрудник, так как этот класс не имеет Rank (), он не будет показывать Rank () в виртуальной таблице.На снимке экрана показано содержимое класса Employee.

"Да, у отладчика недостаточно информации о типе, чтобы определить длину массива. Поэтому он отображает только первый элемент, если он не переопределен."

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

1 голос
/ 07 февраля 2012

Я полагаю, это потому, что в цепочке наследования Manager нет возможных переопределений вашей функции Rank, хотя она и виртуальная. Другими словами, я думаю, что ваш класс должен знать, где переопределяемые виртуальные функции, чтобы правильно распределить вызов функции, что означает, что реализация должна хранить указатели на виртуальные функции. Если никто не может переопределить функции, в диспетчере нет никакой двусмысленности и нет причин сохранять другой указатель в виртуальной таблице.

Вы должны быть в состоянии проверить, выполнив точно такое же упражнение с вашим экземпляром JuniorManager: поскольку нам нужно поддерживать указатель на функцию Rank менеджера в экземплярах JuniorManager, поскольку у нас есть переопределенная функция Rank, мы должны виртуальный указатель в vtable таблицы JuniorManager.

Теперь мне любопытно. Не могли бы вы проверить это для нас и сообщить об этом?

1 голос
/ 07 февраля 2012

Возможно, это связано с тем, что Manager является производным от Employee, но у Employee нет метода Rank. Следовательно, когда объект Manager вызывает Rank (), он никогда не должен находиться в виртуальной таблице. Бьюсь об заклад, если вы создаете экземпляр JuniorManager Ранг будет в vtbl.

Для более подробного объяснения см. Проходит ли вызов виртуальной функции C ++ для производного объекта через vtable? , но я считаю, что это правильная причина.

0 голосов
/ 18 января 2013

Переключить свойство компоновщика Linker-> Optimization-> Ссылки на / OPT: NOREF. Visual Studio удаляет ссылки на функции, которые не используются (не определены). С этим переключателем компоновщик не удаляет эти ссылки.

0 голосов
/ 07 февраля 2012

Я думаю, что мы видим здесь странную причуду Visual Studio, которую я не могу объяснить.

Я скопировал код в Visual Studio, чтобы посмотреть, что происходит, и даже попытался добавить:

JuniorManager *p1 = new JuniorManager();

p1 показано как JuniorManager, который является подклассом Manager, который является подклассом Employee.

Во всех случаях отладчик полностью осведомлен о точном статическом типе переменных-указателей и , точном динамическом типе объектов, на которые указывают объекты, а также точном типе vtable и точном типе записи в виртуальной таблице. Однако vtable видим в отладчике только как часть базового класса (Employee), и по какой-то причине отображаются только известные записи для базового класса.

Было бы намного круче, если бы он показывал и остальные записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...