а чисто виртуальные деструкторы - бывают?
От: Дарней Россия  
Дата: 03.04.03 02:55
Оценка:
кажется мне, что нет... ведь деструктор наследника обязан вызвать деструктор базового класса. А что ему делать, если у базового класса деструктор не определен?
virtual ~Base() = 0 {};

как-то странновато такой вариант выглядит... вроде и чисто виртуальный, и в то же время тело определено.
или вот так, например:
virtual ~Base() = 0 { printf("pure ~Base()"); };

Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re: а чисто виртуальные деструкторы - бывают?
От: SchweinDeBurg Россия http://zarezky.spb.ru/
Дата: 03.04.03 04:17
Оценка:
Здравствуйте, Дарней, Вы писали:

Формально это возможно — все откомпилируется и слинкуется. А в run-time произойдет ошибка — pure virtual function call.
- Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia
Re: Сама идея нерабочая
От: Vi2 Удмуртия http://www.adem.ru
Дата: 03.04.03 04:27
Оценка: :)
Здравствуйте, Дарней, Вы писали:

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

Не бывает чисто виртуального деструктора. Я не знаю пункта стандарта, но по логике ему нет места в ООП.

Класс объявляет чисто виртуальную функцию, принуждая потомков реализовать эту функцию.

Для деструктора ситуация иная — для любого класса деструктор существует. Или определенный пользователем, или созданный компилятором по умолчанию.

Так что сама идея нерабочая.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: а чисто виртуальные деструкторы - бывают?
От: Дарней Россия  
Дата: 03.04.03 04:28
Оценка:
SDB>Формально это возможно
странно, у меня даже не линкуется — пишет unresolved symbol (VC)
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[2]: Сама идея нерабочая
От: Дарней Россия  
Дата: 03.04.03 04:33
Оценка:
Vi2>Для деструктора ситуация иная — для любого класса деструктор существует. Или определенный пользователем, или созданный компилятором по умолчанию.

здесь вопрос не в наличии деструктора, а в его виртуальности. С другой стороны — зачем определение деструктора абстрактному классу?
такое вот объявление:
virtual ~Base() = 0 {};

нормально проходит. Просто я не встречал в литературе объяснение всего этого, вот и пытаюсь разобраться. Как-то странно это все выглядит.
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[3]: Посмотри старую дискуссию
От: Vi2 Удмуртия http://www.adem.ru
Дата: 03.04.03 06:01
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>здесь вопрос не в наличии деструктора, а в его виртуальности. С другой стороны — зачем определение деструктора абстрактному классу?
Д>такое вот объявление:
Д>

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

Д>нормально проходит. Просто я не встречал в литературе объяснение всего этого, вот и пытаюсь разобраться. Как-то странно это все выглядит.

Посмотри старую дискуссию Вопросец
Автор:
Дата: 02.11.02
о чисто виртуальных функциях. Там вроде есть и ответ на твои вопросы.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[3]: а чисто виртуальные деструкторы - бывают?
От: SchweinDeBurg Россия http://zarezky.spb.ru/
Дата: 03.04.03 06:23
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>странно, у меня даже не линкуется — пишет unresolved symbol (VC)


Не, я точно однажды такое собрал по глупости, только очень давно, не помню — мелкософтом или борландом.
- Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia
Re[2]: Сама идея нерабочая
От: WeCom Беларусь  
Дата: 03.04.03 06:31
Оценка: 33 (3)
Здравствуйте, Vi2, Вы писали:

Vi2>Не бывает чисто виртуального деструктора. Я не знаю пункта стандарта, но по логике ему нет места в ООП.

Бывает. Чисто виртуальный — это НЕ значит "НЕ имеющий реализации". Стандарт разрешает чистовиртуальным методам иметь и определение (реализацию)

Vi2>Класс объявляет чисто виртуальную функцию, принуждая потомков реализовать эту функцию.

Так если в базовом классе обьявлен виртуальный деструктор (неважно pure или нет), то в каждом наследнике обязательно он будет перекрыт. Так что с этим все в порядке. Другое дело, если у базового чистовиртуально деструктора нет определения. Тогда будет ошибка при линковке.
Вижу следующее применение чистовиртуальных деструкторов (с определением). Если надо запретить создание экземпляров базового класса и одновременно не требовать перекрыть ни один метод базового класса (кроме деструктора ни одного чистовирт. метода). Ценность сомнительна, но стандарт так делать разрешает.
Re[3]: Сама идея нерабочая
От: oleg_vas  
Дата: 03.04.03 06:43
Оценка: 18 (1)
Здравствуйте, WeCom, Вы писали:

WC>Здравствуйте, Vi2, Вы писали:


Vi2>>Не бывает чисто виртуального деструктора. Я не знаю пункта стандарта, но по логике ему нет места в ООП.

WC>Бывает. Чисто виртуальный — это НЕ значит "НЕ имеющий реализации". Стандарт разрешает чистовиртуальным методам иметь и определение (реализацию)

Vi2>>Класс объявляет чисто виртуальную функцию, принуждая потомков реализовать эту функцию.

WC>Так если в базовом классе обьявлен виртуальный деструктор (неважно pure или нет), то в каждом наследнике обязательно он будет перекрыт. Так что с этим все в порядке. Другое дело, если у базового чистовиртуально деструктора нет определения. Тогда будет ошибка при линковке.
WC>Вижу следующее применение чистовиртуальных деструкторов (с определением). Если надо запретить создание экземпляров базового класса и одновременно не требовать перекрыть ни один метод базового класса (кроме деструктора ни одного чистовирт. метода). Ценность сомнительна, но стандарт так делать разрешает.

Полностью согласен. А по поводу литературы, то я эту технику встречал в Маерса "Effective C++". Вот выдержка с его статьи:
Finally, it's worth mentioning that it can be convenient to declare pure virtual destructors in some classes. Recall that pure virtual functions result in abstract classes — classes that can't be instantiated (i.e., you can't create objects of that type). Sometimes, however, you have a class that you'd like to be abstract, but you don't happen to have any functions that are pure virtual. What to do? Well, because an abstract class is intended to be used as a base class, and because a base class should have a virtual destructor, and because a pure virtual function yields an abstract class, the solution is simple: declare a pure virtual destructor in the class you want to be abstract. ¤ Item E14, P20

Here's an example: ¤ Item E14, P21

class AWOV { // AWOV = "Abstract w/o
// Virtuals"
public:
virtual ~AWOV() = 0; // declare pure virtual
// destructor
};
This class has a pure virtual function, so it's abstract, and it has a virtual destructor, so you can rest assured that you won't have to worry about the destructor problem. There is one twist, however: you must provide a definition for the pure virtual destructor: ¤ Item E14, P22

AWOV::~AWOV() {} // definition of pure
// virtual destructor
You need this definition, because the way virtual destructors work is that the most derived class's destructor is called first, then the destructor of each base class is called. That means that compilers will generate a call to ~AWOV even though the class is abstract, so you have to be sure to provide a body for the function. If you don't, the linker will complain about a missing symbol, and you'll have to go back and add one. ¤
Re[3]: Сама идея нерабочая
От: WeCom Беларусь  
Дата: 03.04.03 06:52
Оценка: +1
Здравствуйте, Дарней, Вы писали:

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


Наоборот, нет никакого смысла абстрактному классу не иметь виртуального деструктора. Особенно, когда абстрактный класс представляет собой чисто "интерфейс", то есть содержит только чистовиртуальные методы. Ведь предполагается, что только в одном месте программы будет создаваться обьект определенного наследника, а во всех остальных работа с этим обьектом будет идти через базовый класс (интерфейс), включая и удаление обьекта. А для того, чтобы через базовый класс нормально удалять наследники, деструктор ДОЛЖЕН быть виртуальным.
Re: а чисто виртуальные деструкторы - бывают?
От: Bell Россия  
Дата: 03.04.03 06:53
Оценка: 3 (1)
Здравствуйте, Дарней, Вы писали:

...

12.4/7
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any
derived class are created in the program, the destructor shall be defined. If a class has a base class with a
virtual destructor, its destructor (whether user or implicitly declared) is virtual.


Т.е. деструктор может быть чисто виртуальным, но если существуют неабстрактные наследники, то жтот днструктор должен быть определен (при этом оставаясь чисто виртуальным)
Любите книгу — источник знаний (с) М.Горький
Re[3]: Как-то не подумал о таком...
От: Vi2 Удмуртия http://www.adem.ru
Дата: 03.04.03 06:55
Оценка:
Здравствуйте, WeCom, Вы писали:

WC>... Если надо запретить создание экземпляров базового класса и одновременно не требовать перекрыть ни один метод базового класса...

Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[3]: Сама идея нерабочая
От: WeCom Беларусь  
Дата: 03.04.03 06:57
Оценка:
Здравствуйте, WeCom, Вы писали:

WC>Вижу следующее применение чистовиртуальных деструкторов (с определением). Если надо запретить создание экземпляров базового класса и одновременно не требовать перекрыть ни один метод базового класса (кроме деструктора ни одного чистовирт. метода). Ценность сомнительна, но стандарт так делать разрешает.


Возможно кому-то интересен пример, где мог бы быть применен описанный подход. По моему совсем не скромному мнению, например, деструктор IUnknown'а мог бы вполне быть чистовиртуальным.
А чисто виртуальные деструкторы - бывают?
От: Павел Кузнецов  
Дата: 03.04.03 07:20
Оценка: 144 (16)
#Имя: FAQ.cpp.virtual_dtor
Д> кажется мне, что нет... ведь деструктор наследника обязан вызвать деструктор
Д> базового класса. А что ему делать, если у базового класса деструктор не определен?

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

Д>
Д> 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
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: а чисто виртуальные деструкторы - бывают?
От: Дарней Россия  
Дата: 03.04.03 07:31
Оценка:
теперь намного понятнее. спасибо
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[4]: Сама идея нерабочая
От: MaximE Великобритания  
Дата: 03.04.03 07:33
Оценка:
Здравствуйте, WeCom, Вы писали:

WC>Возможно кому-то интересен пример, где мог бы быть применен описанный подход. По моему совсем не скромному мнению, например, деструктор IUnknown'а мог бы вполне быть чистовиртуальным.


Это бессмыслено, т.к. наследники IUnknown'а никогда не создаются клиентом по new и попыток удалить их delete'ом тоже не должно быть. Управление lifetime'ом объектов делегировано AddRef/Release.

Деструктор IUnknown, скорее, должен был бы быть protected (хотя само наличие деструктора, вероятно, вызвало бы проблемы в языках, отличных от С++).
Re[2]: а чисто виртуальные деструкторы - бывают?
От: Михаил Можаев Россия www.mozhay.chat.ru
Дата: 03.04.03 07:43
Оценка:
Здравствуйте, SchweinDeBurg, Вы писали:

SDB>Формально это возможно — все откомпилируется и слинкуется. А в run-time произойдет ошибка — pure virtual function call.


Ошибки не будет. Пример:
#include <iostream>

struct A
{
    virtual ~A() = 0;
};

A::~A()
{
    std::cout << "A::~A()\n";
}

struct B : public A
{
    ~B()
    {
        std::cout << "B::~B()\n";
    }
};

int main()
{
    B b;
    return 0;
}
... << RSDN@Home 1.0 beta 6a >>
Re[5]: Сама идея нерабочая
От: WeCom Беларусь  
Дата: 03.04.03 11:58
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Это бессмыслено, т.к. наследники IUnknown'а никогда не создаются клиентом по new и попыток удалить их delete'ом тоже не должно быть. Управление lifetime'ом объектов делегировано AddRef/Release.


ME>Деструктор IUnknown, скорее, должен был бы быть protected (хотя само наличие деструктора, вероятно, вызвало бы проблемы в языках, отличных от С++).


Нда, думал об одном, а написал другое. Я прдеставил ситуацию, когда решается реализовать управление временем жизни обьекта через подсчет ссылок и эту функциональность поместить в базовый класс. Т.е. в базовом классе определены (невиртуальные) методы AddRef и Release, внутри Release delete this;. Тогда, то и был бы полезен чистовиртуальный деструктор.
В общем к существующей реализации IUnknown'а это относится постольку-поскольку.
Re[2]: а чисто виртуальные деструкторы - бывают?
От: Lorenzo_LAMAS  
Дата: 03.04.03 13:12
Оценка:
Здравствуйте, SchweinDeBurg, Вы писали:

SDB>Здравствуйте, Дарней, Вы писали:


SDB>Формально это возможно — все откомпилируется и слинкуется. А в run-time произойдет ошибка — pure virtual function call.


Это неправильное мнение. Посмотри, в качестве примера CObject (в .Нет — в новом МФЦ).
Деструктор может быть чисто виртуальным и я думаю можно придумать ситуацию , когда это надо. Главное — должно быть определение.
Of course, the code must be complete enough to compile and link.
Re[3]: Сама идея нерабочая
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 03.04.03 15:34
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>такое вот объявление:

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

Д>нормально проходит.

А не должно. Запрещается определять чисто виртуальную функция внутри определения класса.
Алексей Кирдин
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.