Вызов виртуальной функции из деструктора

Это безопасно?

class Derived: public PublicBase, private PrivateBase { ... ~Derived() { FunctionCall(); } virtual void FunctionCall() { PrivateBase::FunctionCall(); } } class PublicBase { virtual ~PublicBase(){}; virtual void FunctionCall() = 0; } class PrivateBase { virtual ~PrivateBase(){}; virtual void FunctionCall() { .... } } PublicBase* ptrBase = new Derived(); delete ptrBase; 

Этот код иногда прерывается с IP-адресом в плохом адресе.

Это не очень хорошая идея, чтобы вызвать виртуальную функцию для конструктора, понятна для всех.

Из таких статей, как http://www.artima.com/cppsource/nevercall.html Я понимаю, что деструктор также является не очень хорошим местом для вызова виртуальной функции.

Мой вопрос: «Это правда?» Я тестировал VS2010 и VS2005 и вызывается PrivateBase :: FunctionCall. Неопределенное поведение?

Я собираюсь пойти против streamа здесь … но сначала я должен предположить, что ваш деструктор PublicBase является виртуальным, так как иначе Derived destructor никогда не будет вызван.

Обычно не рекомендуется вызывать виртуальную функцию из конструктора / деструктора

Причиной этого является то, что динамическая отправка странная во время этих двух операций. Фактический тип объекта изменяется во время строительства и он снова изменяется во время разрушения. Когда деструктор выполняется, объект имеет именно тот тип и никогда не является производным от него. Динамическая диспетчеризация действует все время, но конечный перехватчик виртуальной функции будет меняться в зависимости от того, где вы находитесь в иерархии.

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

Но

В вашем конкретном случае конечный переопределитель (по крайней мере, для этой части иерархии) находится выше вашего уровня. Более того, вы вообще не используете динамическую отправку . Вызов PrivateBase::FunctionCall(); статически разрешена и фактически эквивалентна вызову любой не виртуальной функции. Тот факт, что функция виртуальна или нет, не влияет на этот вызов.

Так что да, это прекрасно, как вы делаете, хотя вам придется объяснить это в обзорах кода, поскольку большинство людей изучают мантру правила, а не причину этого.

Это безопасно?

Да. Вызов виртуальной функции от конструктора или деструктора отправляет эту функцию, как если бы динамический тип объекта был в настоящее время сконструирован или уничтожен. В этом случае он вызывается из деструктора Derived , поэтому он отправляется в Derived::FunctionCall (который, в вашем случае, вызывает PrivateBase::FunctionCall не виртуально). Все это четко определено.

«Неплохая идея» – вызывать виртуальные функции от конструктора или деструктора по трем причинам:

  • Это вызовет неожиданное поведение, если вы вызовете его из базового classа и (ошибочно) ожидаете, что он будет отправлен на переопределение в производном classе;
  • Это приведет к неопределенному поведению, если оно чисто виртуальное;
  • Вам придется объяснять свое решение людям, которые считают, что это всегда неправильно.

В общем, не рекомендуется вызывать виртуальную функцию, если объект classа, к которому он может быть отправлен (т. Е. «Полный» объект самого производного classа), полностью построен. И это не тот случай

  • пока все конструкторы не закончат выполнение
  • после того, как любой деструктор завершит выполнение

Это очень плохая идея, согласно scott: link

Это то, что я собрал и выполнил, чтобы помочь мне лучше понять процесс уничтожения, вы также можете найти его полезным

 #include  using namespace std; class A { public: virtual void method() { cout << "A::method" << endl; } void otherMethod() { method(); } virtual ~A() { cout << "A::destructor" << endl; otherMethod(); } }; class B : public A { public: virtual void method() { cout << "B::method" << endl; } virtual ~B() { cout << "B::destructor" << endl; } }; int main() { A* a = new B(); a->method(); delete a; } 
Interesting Posts

Поддерживает ли Win7 планирование резервного копирования образа системы?

SSO с CAS или OAuth?

Что такое трассировка стека, и как я могу использовать ее для отладки ошибок моего приложения?

Установить приложение через usb: устройство временно ограничено

Проблема при использовании пользовательского шрифта – «родной шрифт не может быть создан»

Rails DB Migration – Как удалить таблицу?

Почему пинг на конкретный адрес отличается от страны?

Преобразование Word в HTML – Потеря качества изображения

C #: исключение из памяти

Как анализировать файл ini с помощью Boost

Как заставить Windows 7 НЕ использовать корзину для утилизации на съемном диске?

Найти и убить процесс в одной строке с помощью bash и regex

Какой видео кодек ставит CPU / GPU под минимальную нагрузку при декодировании?

Windows 7 – мои шрифты скрыты

Отображение негативных меток времени в Excel 2007chart

Давайте будем гением компьютера.