Где находится чистая виртуальная функция в C++?

В какой виртуальной таблице будет находиться чистая виртуальная функция? В базовом классе или производном классе?

Например, как выглядит виртуальная таблица в каждом классе?

class Base {

  virtual void f() =0;
  virtual void g();
}


class Derived: public Base{

  virtual void f();
  virtual void g();

}

person skydoor    schedule 31.03.2010    source источник
comment
Связанный вопрос: stackoverflow.com/questions/2549618   -  person Artem Sokolov    schedule 31.03.2010
comment
Кто сказал, что есть виртуальный стол? Стандарт ничего не говорит о них, и поэтому они являются плодом человеческого воображения :-) Если вам нужны подробности реализации конкретного компилятора, вам нужно упомянуть компилятор, который вы используете.   -  person Martin York    schedule 31.03.2010


Ответы (4)


g++ -fdump-class-hierarchy layout.cpp создает файл layout.cpp.class. Содержимое layout.cpp.class покажет следующее:

Vtable for Base
Base::_ZTV4Base: 4u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI4Base)
16    __cxa_pure_virtual
24    Base::g

Class Base
   size=8 align=8
   base size=8 base align=8
Base (0x7ff893479af0) 0 nearly-empty
    vptr=((& Base::_ZTV4Base) + 16u)

Vtable for Derived
Derived::_ZTV7Derived: 4u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI7Derived)
16    Derived::f
24    Derived::g

Class Derived
   size=8 align=8
   base size=8 base align=8
Derived (0x7ff893479d90) 0 nearly-empty
    vptr=((& Derived::_ZTV7Derived) + 16u)
  Base (0x7ff893479e00) 0 nearly-empty
      primary-for Derived (0x7ff893479d90)

Удаление «чистоты» f изменяет пятую строку на:

16    Base::f
person Artem Sokolov    schedule 31.03.2010

У каждого класса есть своя виртуальная таблица. Запись для f в Base будет NULL, а запись в Derived будет указателем на код реализованного метода.

person Tony the Pony    schedule 31.03.2010
comment
Ну, не совсем NULL. В VC++ запись представляет собой адрес функции CRT _purecall: thetweaker.wordpress.com/2010/06/03/ - person Ofek Shilon; 14.06.2010

Запись vtable будет в базовом классе.

Почему? Потому что у вас может быть базовый тип указателя, который содержит адрес объекта производного типа, и при этом вызывать метод для переменной указателя базового типа.

Чистый виртуальный просто сообщает компилятору, что производные типы должны предоставлять свою собственную реализацию, и они не могут полагаться на реализацию базового класса (если она даже указана в базовом классе)

person Brian R. Bondy    schedule 31.03.2010

В обоих на самом деле. Базовый класс vtable будет иметь слот для чистой виртуальной функции, указывающей на что-то вроде pure_virtual_function_called() заглушки, которая, вероятно, прервет программу, в то время как производный класс vtable будет иметь указатель на реальную реализацию.

person Nikolai Fetissov    schedule 31.03.2010