Д> кажется мне, что нет... ведь деструктор наследника обязан вызвать деструктор
Д> базового класса. А что ему делать, если у базового класса деструктор не определен?

Чисто виртуальные деструкторы бывают. В этом отношении деструкторы ведут себя так же, как и любые другие функции, за упомянутым исключением, что деструктор базового класса вызывается деструктором потомка вне зависимости от желания программиста.

Д>
Д> virtual ~Base() = 0 {};
Д>


Д> как-то странновато такой вариант выглядит...


Этот вариант выглядит, действительно, немного "странновато". Но не потому, что есть определение чисто виртуальной функции, а потому что это определение совмещено с ее объявлением. Текущая версия стандарта подобного не разрешает. Т.е. чисто виртуальные функции можно определять только вне тела класса.

Д> вроде и чисто виртуальный, и в то же время тело определено.


"Чистая виртуальность" и наличие определения вовсе не взаимоисключающие вещи. Чисто виртуальной функцию делают для того, чтобы гарантировать, что (1) она будет обязательно реализована в одном из наследников и что (2) класс будет абстрактным. Чисто виртуальными деструкторы обычно делают именно для (2). Т.е., если, например, в классе больше виртуальных функций нет, но хочется, чтобы класс был абстрактным.

Любая виртуальная функция, в том числе и чисто виртуальная, может быть вызвана невиртуально. Это означает, что при желании чисто виртуальные функции можно определять, но вызвать их можно будет только невиртуально. В случае деструктора этот невиртуальный вызов генерируется компилятором в деструкторах классов-наследников, поэтому даже чисто виртуальные деструкторы обязательно должны быть определены. Например:

class C
{
public:
  virtual void f();
  virtual void g() = 0;
  virtual ~C() = 0;
};

void C::f()
{
}

void C::g()
{
}

void C::~C()
{
}

class D : public C
{
public:
  void f();
  void g();
  ~D();
};

void D::f()
{
  C::f(); // невиртуальный вызов C::f
}

void D::g()
{
  C::g(); // невиртуальный вызов C::g, значит чисто виртуальная C::g должна быть определена
}

void D::~D()
{
  // неявный невиртуальный вызов C::~C
}
Posted via RSDN NNTP Server 1.5 beta
Автор: Павел Кузнецов    Оценить