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

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

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. Неопределенное поведение?

4 Solutions collect form web for “Вызов виртуальной функции из деструктора”

Я собираюсь пойти против 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

Клонирование жестких дисков из аппаратного RAID-массива?

Где OS X Mountain Lion хранит данные Notes?

Нестандартные параметры шаблона

Сколько символов можно сопоставить с Unicode?

ConfigurationManager не сохраняет настройки

Совместим ли Sass 3.3 с Compass?

Кто изменил мои функциональные клавиши? Функции F7 и F8 были перезаписаны в Windows 7

Как вы запрашиваете статические .html-файлы в папке ~ / Views в ASP.NET MVC?

Parse цитирует строки с boost :: spirit

Настройка учетных записей Linux-оболочки для общего доступа

Как синхронизированная работа в Java

OS X «Смертельная спираль»? Невозможно запустить новые процессы, в конечном итоге становится непригодным

Отменяемые и неизменяемые объекты

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

Запуск тестов junit параллельно в сборке Maven?

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