Зачем нужен невиртуальный деструктор?
От: Muxa  
Дата: 09.12.10 08:24
Оценка:
Представьте себе иерархию классов.
Разработчик самого базового из них не сделал деструктор виртуальным.
Для чего он мог это сделать?
Re: Зачем нужен невиртуальный деструктор?
От: kaa.python Ниоткуда РСДН профессионально мёртв и завален ватой.
Дата: 09.12.10 08:32
Оценка: :)))
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

Чтоб те, кто будут работать с его иерархией, прочувствовали всю прелесть процесса отладки.
Re: Зачем нужен невиртуальный деструктор?
От: jazzer Россия Skype: enerjazzer
Дата: 09.12.10 08:32
Оценка: 3 (2) +9
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

Как вариант — не предназначал класс для полиморфного удаления.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Зачем нужен невиртуальный деструктор?
От: Suna Bozzu  
Дата: 09.12.10 08:35
Оценка: +3
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?
Возможно, для того, что бы не создавалась таблица виртуальных функций (для увеличения быстродействия).
Но, если изначально предполагалось использовать этот класс в качестве базового, то такое решение очень спорное (на мой взгляд).
Re[2]: Зачем нужен невиртуальный деструктор?
От: Muxa  
Дата: 09.12.10 08:42
Оценка:
SB>Возможно, для того, что бы не создавалась таблица виртуальных функций (для увеличения быстродействия).
неужели увеличение производительности в этом случае будет (может быть) ощутимым?
я имею в виду, что конечно можно привести синтетический пример такого кода, но в реальных условиях, программист вряд ли бы принял решения о реализации такой иерархии. (это было личное мнение)
Re: Зачем нужен невиртуальный деструктор?
От: datura-inoxia  
Дата: 09.12.10 08:49
Оценка: 2 (1) +1
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

Например, чтобы запретить удаление по указателю на базовый класс.
Это может быть полезно, например, при передаче указателя на базовый класс в качестве callback'a куда-нибудь. Чтобы в этом где-нибудь, могли вызывать методы интерфейса, но не могли удалять объект.

Чтобы выразить это явно, а не превращать увлекательную отладку странных глюков, деструктор нужно объявить как protected.
Re: Зачем нужен невиртуальный деструктор?
От: telek1024  
Дата: 09.12.10 08:50
Оценка: -1
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

  1. Забыл
  2. Не знал
  3. Класс не предназначен для наследования. В этом случае в VMT нет смысла. В большинстве случаев не очень большой прирост в производительности (минус один jump) и по памяти (одно машинное слово на экземпляр класса), но может профилировщик сказал обратное?
Re[3]: Зачем нужен невиртуальный деструктор?
От: jazzer Россия Skype: enerjazzer
Дата: 09.12.10 08:53
Оценка: 2 (1) +3
Здравствуйте, Muxa, Вы писали:

SB>>Возможно, для того, что бы не создавалась таблица виртуальных функций (для увеличения быстродействия).

M>неужели увеличение производительности в этом случае будет (может быть) ощутимым?
может
Не говоря уже о том, наличие вирт. деструктора автоматически переводит класс в категорию не-POD + non-trivial destructor.

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

хз. Надо смотреть на иерархию. Это С++, а не Java, наследование тут используется по очень разным поводам.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Зачем нужен невиртуальный деструктор?
От: Muxa  
Дата: 09.12.10 08:54
Оценка:
T>Забыл
T>Не знал
это сделано сознательно

T>Класс не предназначен для наследования. В этом случае в VMT нет смысла.

Класс предназначен для наследования.

T>В большинстве случаев не очень большой прирост в производительности (минус один jump) и по памяти (одно машинное слово на экземпляр класса), но может профилировщик сказал обратное?

про профилировщик не понял. система еще в разработке, появляются производные классы.
Re[3]: Зачем нужен невиртуальный деструктор?
От: Suna Bozzu  
Дата: 09.12.10 08:58
Оценка: 2 (1) +1
Здравствуйте, Muxa, Вы писали:

SB>>Возможно, для того, что бы не создавалась таблица виртуальных функций (для увеличения быстродействия).

M>неужели увеличение производительности в этом случае будет (может быть) ощутимым?
M>я имею в виду, что конечно можно привести синтетический пример такого кода, но в реальных условиях, программист вряд ли бы принял решения о реализации такой иерархии. (это было личное мнение)
Это может быть актуально, когда экземпляры класса создаются часто и в больших количествах (типа "умных указателей" или чего то подобного). Но, я так понимаю, здесь другой случай..
Re: Зачем нужен невиртуальный деструктор?
От: Alexander G Украина  
Дата: 09.12.10 09:00
Оценка: +1
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

Для того, чтобы избежать оверхед на виртуальный деструктор там, где не планируется полиморфное удаление.
Пример — boost::noncopyable
Русский военный корабль идёт ко дну!
Re: Зачем нужен невиртуальный деструктор?
От: slava_phirsov Россия  
Дата: 09.12.10 09:14
Оценка: +2
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

Где-то читал (сам не проверял!) , что компиляторы умеют уложить экземпляр класса в один регистр (EAX) при возврате из функции по значению. При этом размер экземпляра, естественно, должен быть минимален. Если у экземепляра имеется таблица виртуальных методов, то такой фокус вряд ли пройдет.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[2]: Зачем нужен невиртуальный деструктор?
От: dilmah США  
Дата: 09.12.10 09:14
Оценка:
T>В большинстве случаев не очень большой прирост в производительности (минус один jump)

считать в инструкциях не очень осмысленно. Вызов невиртуального деструктора в большинстве случаев инлайнится, то есть никаких переходов, а тело функции оптимизируется непосредственно в контектсе вызова. Виртуальный -- это косвенный вызов со всеми прелестями сброса конвейера и отсутсвия оптимизации в контексте вызова.
Re: Зачем нужен невиртуальный деструктор?
От: rg45 СССР  
Дата: 09.12.10 09:55
Оценка: 1 (1) +1
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

Реализовать гибкую стратегию владения объектами можно и без виртуальных деструкторов. Приведу пример. Я определяю некий абстракный интерфейс, состоящий полностью из чисто виртуальных функций:
class IFoo
{
public:

  virtual void bar() = 0;
  virtual void baz() = 0;

protected:
  IFoo() { }
};

Причем деструктор этого абстрактного класса я намеренно объявляю невиртуальным и защищенным, тем самым как бы подчеркивая, что стратегия владения объектами выбирается разработчиком производных классов. При этом у разработчика производного класса есть две возможности: 1) (традиционный) сделать деструктор производного класса открытым и виртуальным; 2) сделать деструктор невиртуальным и защищенным, а для создания объектов реализовать фабричный метод.

Пример второго варианта:
using boost::shared_ptr;

class FooDerived1 : public IFoo
{
public:

  virtual void bar();
  virtual void baz();

  static shared_ptr<FooDerived1> create_instance(/*possible arguments*/);
  {
    return shared_ptr<FooDerived1>(new FooDerived(/*possible arguments*/));
  }

protected:
  FooDerived1();
};

class FooDerived2 : public IFoo { /*...*/ };
class FooDerived3 : public IFoo { /*...*/ };

А вот теперь замечательный момент: умный указатель производного типа, возвращаемый фабричным методом create_instance, легко преобразуется в умный указатель абстрактного типа. Это позволяет владеть объектами и корректно удалять их полиморфно:
int main()
{
  typedef std::vector<boost::shared_ptr<IFoo> > Items;

  Items items;
  items.push_back(FooDerived1::create_instance(/*possible arguments*/));
  items.push_back(FooDerived2::create_instance(/*possible arguments*/));
  items.push_back(FooDerived3::create_instance(/*possible arguments*/));

  //...
}

Преимущество такого подхода: отделение основной функциональности абстрактных классов от способов владения конкретными объектами. Т.о. в прикладной программе точка создания объектов как бы изолирована от использования этих объектов. Это улучшает структурированность кода, тестируемость и пр. и др.
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: Зачем нужен невиртуальный деструктор?
От: Erop Россия  
Дата: 09.12.10 12:22
Оценка: 1 (1) -1
Здравствуйте, Muxa, Вы писали:

M>про профилировщик не понял. система еще в разработке, появляются производные классы.


Выделенное действие неясно. У вас архитектуру на ходу меняют что ли?
Да и вообще у тебя слишком сложный вопрос. Слишком общий. Опиши иерархию, что ли.
А то я легко могу придумать тебе пример класса, который базовый, но вообще без деструктора

Например так:
template<typename TAllocator> struct CAllocatedOn {
    void* operator new( size_t s ) { return TAllocator::Alloc( s ); }
    void operator delete( void* p ) { TAllocator::Free( p ); }
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Зачем нужен невиртуальный деструктор?
От: andrey_nado  
Дата: 09.12.10 14:44
Оценка:
Здравствуйте, rg45, Вы писали:

А что будет в следующем случае:
boost::shared_ptr<IFoo> p = items[0];
// Объект items удалён, p - единственный владелец указателя
p->bar();
// А теперь p должен быть уничтожен с удалением объекта класса IFoo
// Какой деструктор будет вызван?
Re[3]: Зачем нужен невиртуальный деструктор?
От: rg45 СССР  
Дата: 09.12.10 15:05
Оценка:
Здравствуйте, andrey_nado, Вы писали:

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


_>А что будет в следующем случае:

_>
_>boost::shared_ptr<IFoo> p = items[0];
_>// Объект items удалён, p - единственный владелец указателя
p->>bar();
_>// А теперь p должен быть уничтожен с удалением объекта класса IFoo
_>// Какой деструктор будет вызван?
_>


Будет вызван деструктор производного класса, я пример приводил для иллюстрации именно этого факта. Объясняется это просто: в момент создания экземпляра boost::shared_ptr в нем запоминается не только указатель на объект, но также и функционал deleter, который обеспечивает корректное удаление адресуемых объектов, даже после преобразований.

Еще один аргумент. Деструктор абстрактного класса IFoo в моем примере объявлен защищенным, это является гарантией того, что извне класса этот деструктор не может быть вызван. Поэтому, если Ваша программа откомпилировалась без ошибок, на этот счет можете не волноваться
--
Справедливость выше закона. А человечность выше справедливости.
Re: Зачем нужен невиртуальный деструктор?
От: minorlogic Украина  
Дата: 09.12.10 19:32
Оценка: -1
Здравствуйте, Muxa, Вы писали:

M>Представьте себе иерархию классов.

M>Разработчик самого базового из них не сделал деструктор виртуальным.
M>Для чего он мог это сделать?

Чтобы спрашивать это на собеседовании и выявлять джуниоров.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[4]: Зачем нужен невиртуальный деструктор?
От: ankf  
Дата: 09.12.10 19:37
Оценка:
SB>Это может быть актуально, когда экземпляры класса создаются часто и в больших количествах (типа "умных указателей" или чего то подобного). Но, я так понимаю, здесь другой случай..

Помоему при создании класса основные "трудозатраты" это работа менеджера памяти и выделение куска. А косвенный переход через виртуальную таблицу — это брызги для моряков по сравнению с выделением памяти и копированием.
Я программист, я Иван Помидоров, хватить трепатся — наш козырь error.
Re[2]: Зачем нужен невиртуальный деструктор?
От: Muxa  
Дата: 09.12.10 19:52
Оценка: +1 :)
M>Чтобы спрашивать это на собеседовании и выявлять джуниоров.
сомневаюсь что задумка создателей языка была именно такая.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.