crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

5 страниц V  < 1 2 3 4 5 >  
Ответить в данную темуНачать новую тему
> C++, виртуальный деструктор
Алексей1153
  опции профиля:
сообщение 17.8.2010, 19:24
Сообщение #21


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


нет, речь не про виртуальный деструктор, а про явный вызов виртуальных функций из деструктора предка
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 17.8.2010, 19:27
Сообщение #22


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Ты про чисто виртуальные функции или просто виртуальные?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 17.8.2010, 19:51
Сообщение #23


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Щас сделаю тест, самому охота вспомнить )

хм, выяснилась интересная вещь. Ни Креатор, ни Студия (№6, №9) просто не позволяют так сделать ещё на уровне линковки

class A
{
public:
    virtual void F()=0;

    void CallF()
    {
        F();
    }

    virtual ~A()
    {
        F();//<<<<< на это ругань
    }
};

class B:public A
{
public:
    void F()
    {
        int iii=1;
    }

    void CallF()
    {
        F();
    }

    ~B()
    {
        F();
    }
};


void main()
{
    B b;
    b.CallF();
}



Цитата
unresolved external symbol "public: virtual void __thiscall A::F(void)" (?F@A@@UAEXXZ)


Цитата
undefined reference to `A::F()'


А ведь я помню, нарвался как то на подобное, но не могу вспомнить, как именно

Сообщение отредактировал Алексей1153 - 17.8.2010, 19:54
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 17.8.2010, 20:21
Сообщение #24


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


Цитата(BRE @ 17.8.2010, 22:20) *
На сколько я помню, при удалении объекта с виртуальным деструктором, будет вызван деструктор из его vtbl. После его отработки, vtbl будет переключена на таблицу базового класса и будет вызван его деструктор и т.д. Даже если ты будешь удалять объект по указателю на его базовый класс. В этом и смысл.
А вот с конструкторами такое не пройдет, они не могут быть виртуальными. Поэтому, в конструкторе будет вызван виртуальный метод того класса, конструктор которого в данный момент работает, даже если в производном классе он переопределен.

абсолютно верно. именно так и будет.
если в классе виртуальная функция определена, то она может быть вызвана в деструкторе этого класса и в деструкторах классов-наследников, если вдруг потребуется. для каждого класса могут использоваться его функции и функции прародителей. для деструктора нет ограничений. они есть только для конструктора - так как в момент создания элемента виртуальной таблицы и указателя this просто ещё нет.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 18.8.2010, 4:26
Сообщение #25


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Алексей1153 @ 17.8.2010, 22:41) *
... вызываются ли виртуальные функции в деструкторе (низя)
нет, у меня именно пустой деструктор (мне нечего было подчищать при завершении работы класса), а насчёт того, что нельзя, я тоже краем уха где-то слышал.
Цитата(Алексей1153 @ 17.8.2010, 22:41) *
... производится ли где-то явное приведение типа с последующим изменением начала объекта
вот это не понял, что значит с изменением начала объекта?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 18.8.2010, 6:50
Сообщение #26


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Цитата(Litkevich Yuriy @ 18.8.2010, 7:26) *
а насчёт того, что нельзя, я тоже краем уха где-то слышал.

поскольку точно не могу факт привести, не буду придумывать :) Лучше всегда поставить эксперимент на месте и проверить в отладчике.

Цитата(Litkevich Yuriy @ 18.8.2010, 7:26) *
вот это не понял, что значит с изменением начала объекта?


например
Раскрывающийся текст
    //общий вид сообщения из 4 байтов
    struct SomeMessage
    {
        //флаги, общие для всех сообщений
        BYTE b1:1;
        BYTE b2:1;
        BYTE b3:1;
        BYTE b4:1;
        BYTE b5:1;
        BYTE b6:1;
        BYTE b7:1;
        BYTE b8:1;

        //код сообщения
        BYTE m_Code;

        //разные данные - зависят от m_Code
        WORD m_SomeData;

        virtual ~SomeMessage()
        {
            m_Code=0;
        }

        void FillMe(DWORD dwdRawData)
        {
            //грабля №1 - размер *this равен 8 байтов, а не 4, как ожидается
            //поэтому проверка вернёт false
            if(sizeof(*this)==sizeof(dwdRawData))
            {
                //грабля №2 - запись произошлы бы не в тело структуры, а
                //ровнёхонько в виртуальную таблицу
                *((DWORD*)this)=dwdRawData;
            }
        }
    };


void main()
{
    DWORD dwd=0x110022FF;
    SomeMessage m;
    m.FillMe(dwd);
    //виртуальная таблица была бы испорчена, если бы не проверка №1 в функции

}


Сообщение отредактировал Алексей1153 - 18.8.2010, 6:52
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 18.8.2010, 9:43
Сообщение #27


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


Цитата(Алексей1153 @ 17.8.2010, 20:51) *
хм, выяснилась интересная вещь. Ни Креатор, ни Студия (№6, №9) просто не позволяют так сделать ещё на уровне линковки

ты в первом посте верно написал - при вызове виртуальных функций из деструктора - просто напросто вызовутся функции того класса чей деструктор а не предков.
что стандарт по этому поводу говорит конечно интересно.
а не линкуется, потому что получается вызов чисто виртуальной функции.
Раскрывающийся текст

# include <iostream>
# include <string>

class Parent
{
public:
    /*virtual*/ ~Parent()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
        printData();
    }
    virtual void printData()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class Child : public Parent
{
public:
    Child()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
        m_data = new std::string("hello world");
    }
    void printData()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
        std::cout << *m_data << '\n';
    }
    ~Child()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
        delete m_data;
    }

private:
    std::string* m_data;

};

int main()
{
    Child* child = new Child;
    static_cast<Parent*>(child)->printData();
    delete child;
    return 0;
}



./a.out 
Child::Child()
virtual void Child::printData()
hello world
Child::~Child()
Parent::~Parent()
virtual void Parent::printData()
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 18.8.2010, 10:11
Сообщение #28


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Цитата(Алексей1153 @ 17.8.2010, 22:11) *
функции данного объекта, а не потомков


kwisp, вообще-то, я про потомков говорил ) Ведь назначение виртуальных функций - вызывать методы потомков

Цитата(kwisp @ 18.8.2010, 12:43) *
вызов чисто виртуальной функции.

такой вызов не запрещён вроде :)
Потому что абстрактный объект создать нельзя, а потомки должны обязательно переопределить виртуалки

Сообщение отредактировал Алексей1153 - 18.8.2010, 10:13
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 18.8.2010, 11:16
Сообщение #29


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


Цитата(Алексей1153 @ 17.8.2010, 20:11) *
Будут вызываться функции данного объекта, а не потомков

вот

Цитата(Алексей1153 @ 18.8.2010, 11:11) *
такой вызов не запрещён вроде :)

да ну не верится.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 18.8.2010, 12:20
Сообщение #30


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


что тут верить то :) Проверить, и всё
class A
{
public:
    virtual void F()=0;

    void Call_F()
    {
        F();
    }

    virtual ~A()
    {
    }

};

class B:public A
{
public:
    void F()
    {

    }
};

main()
{

    A* pa =new B;

    pa->F();
    pa->Call_F();
    delete pa;
    pa=0;
}


Сообщение отредактировал Алексей1153 - 18.8.2010, 12:22
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

5 страниц V  < 1 2 3 4 5 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 24.4.2024, 16:15