Вызов виртуального метода из деструктора
От: Barbar1an Украина  
Дата: 05.08.19 13:33
Оценка: :)))
class A
{
public:
    void Normal()
    {
        Virtual();
    }

    virtual void Virtual()
    {
        // это не вызовется  - ОК
    }

};

class B : public A
{
public:

    virtual void Virtual() override
    {
        // это  вызовется -  ЧЕ ЗА?
    }

    ~B()
    {
        Normal();
    }
};

class C : public B
{
public:
    virtual void Virtual() override
    {
        // это не вызовется -  ЧЕ ЗА?
    }
};


int _tmain(int argc, _TCHAR* argv[])
{

    C c;

    return 0;
}
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re: Вызов виртуального метода из деструктора
От: Carc Россия Aml Pages — оперативный блокнот http://www.amlpages.com/home.php
Дата: 05.08.19 13:50
Оценка: 4 (1)
Здравствуйте, Barbar1an, Вы писали:


B>
B>class A
B>{
B>public:
B>    void Normal()
B>    {
B>        Virtual();
B>    }

B>    virtual void Virtual()
B>    {
B>        // это не вызовется  - ОК
B>    }

B>};

B>class B : public A
B>{
B>public:

B>    virtual void Virtual() override
B>    {
B>        // это  вызовется -  ЧЕ ЗА?
B>    }

B>    ~B()
B>    {
B>        Normal();
B>    }
B>};

B>class C : public B
B>{
B>public:
B>    virtual void Virtual() override
B>    {
B>        // это не вызовется -  ЧЕ ЗА?
B>    }
B>};


B>int _tmain(int argc, _TCHAR* argv[])
B>{

B>    C c;

B>    return 0;
B>}
B>


Деструктора C нет, соответтственно вызывается базовый класса B, в момент вызова деструктора класса B таблицы виртуальных функций класса C уже нет. Поэтому и вызывается B::Virtual (через вызов A::Normal)
По моему так!?!
Aml Pages Home
Отредактировано 05.08.2019 13:51 Carc . Предыдущая версия .
Re: Вызов виртуального метода из деструктора
От: Alexander G Украина  
Дата: 05.08.19 13:51
Оценка: 4 (1) +1
Тю, во всех учебниках по С++ про это есть, наверное.

Плюс даже ворнинги статических анализаторов.

Когда деструктор B вызывается, это уже эеземпляр B, а не C.
Технически это сделано переприсвоением vtable указателя.
То же самое с конструкторами.
Re[2]: Вызов виртуального метода из деструктора
От: Barbar1an Украина  
Дата: 05.08.19 13:53
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Тю, во всех учебниках по С++ про это есть, наверное.


AG>Плюс даже ворнинги статических анализаторов.


AG>Когда деструктор B вызывается, это уже эеземпляр B, а не C.

AG>Технически это сделано переприсвоением vtable указателя.
AG>То же самое с конструкторами.

а зачем так сделали?
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[3]: Вызов виртуального метода из деструктора
От: Alexander G Украина  
Дата: 05.08.19 14:47
Оценка: +1
Здравствуйте, Barbar1an, Вы писали:

B>а зачем так сделали?


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

В Delphi так не сделали, но там классы всегда в куче, и всегда по умолчанию зануляются, так что там просто делают проверки на созданность.

MSVC-specific: можно отказаться от инициализации vtable в базе, через __declspec(novtable), тогда в базовых конструкторе/деструкторе вообще нельзя вызывать виртуальные методы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.