Re: Вываливается ошибка "pure virtual function call"
От: Кодт Россия  
Дата: 15.11.04 18:29
Оценка:
Здравствуйте, BlackKhan, Вы писали:

BK>Если есть мысли о причине такой ошибки, буду очень признателен!


Штатный способ получить такую ошибку — вызвать из конструктора/деструктора абстрактный метод косвенным способом
struct Foo
{
  virtual void foo() = 0;
  void bar() { foo(); } // динамический вызов
  Foo()
  {
    foo(); // статический вызов ***
    bar(); // приведёт к PVFC
  }
};

void Foo::foo() {} // если мы статически вызываем, значит, должны определить
// а если не вызываем (закомментируем строку ***), то в определении не нуждаемся

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

Нештатным способом этого можно добиться
— удачно расстреляв память
— нарушив ODR (one definition rule) — что вполне вероятно при рассогласованных DLL

Пример нарушения ODR
///////////////////
// foo.h

struct Foo
{
#ifdef FOO_THEN_BAR
  virtual void foo() = 0;
  virtual void bar() {}
#else
  virtual void bar() {}
  virtual void foo() = 0;
#endif

  Foo();
};

//////////////////
// foo.cpp

#define FOO_THEN_BAR
#include "foo.h"

Foo::Foo() {} // VMT содержит: [0]=PVFC, [1]=&Foo::bar

//////////////////
// bar.h

#include "foo.h"

struct Bar : Foo
{
  void buz() { bar(); }
  Bar() { buz(); } // кажется, всё в порядке: динамический вызов существующего виртуального метода
};

//////////////////
// buz.cpp

//#define FOO_THEN_BAR
#include "bar.h"

struct Buz : Bar
{
  void foo() {} // чтобы класс был не абстрактным
};

main()
{
  Buz trahtibidoh;
  // при конструировании базового подобъекта Buz мы нарвёмся на старую VMT (если RTTI выключено и Bar воспользовался VMT предка)
}
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.