Re: Вызов виртуальной функции в деструкторе (VC 7.0)
От: Андрей Тарасевич Беларусь  
Дата: 23.09.03 01:16
Оценка: 2 (1)
Здравствуйте, comer, Вы писали:

C>Понятное дело что такой вызов не приветствуеться. Но, проведем эксперимент на разных компиляторах.


C>
C>// test.cpp
C>struct A
C>{
C>    ~A() { F(); }
C>    virtual void F() = 0;
C>};

C>struct B: A
C>{
C>    void F() {}
C>};

C>int main()
C>{
C>    B b;
C>    return 0;
C>}
C>


C> ...


C>Ага, а тут это всего лишь сообщение. Но дальше больше. VC 7.0. Компилируем, все хорошо (может какую то галочку забыл нажать в свойствах компиляции?). А вот линкер ругаеться, говорит:

C>
C>test.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall A::F(void)" (?F@A@@$$FUAEXXZ)
C>


C>Спрашиваеться, а почему линкер ищет эту абстрактную функцию? Я понял бы другое сообщения об ошибке, но не такое.


Потому что компилятор соображает, что вызов виртуальной функции 'F()' (как и любой другой виртуальной функции) из деструктора класса 'A' совсем не обязательно делать виртуально. Так как уже на стадии компиляции соврешенно ясно, что вызваться будет именно функция 'A::F()', компилятор в целях оптимизации генерирует прямой (невиртуальный) вызов именно функции 'A::F()' из деструктора класса 'A', взваливая задачу связывания этого вызова на хрупкие плечи линкера. Линкер, разумеется, связать этот вызов не может, ибо тела у функции 'A::F()' нет. Отсюда и сообщение об ошибке.

Я думаю, что если бы ты добавил в свой код определение функции 'A::F()', то VC7.0 молча бы скомпилировал этот код.

struct A
{
  ~A() { F(); }
  virtual void F() = 0;
};

void A::F()
{
}


Правда легальным от этого данный код бы не стал все равно, ибо такие pure virtual функии разрешается вызвать только при помощи указания полностью квалифицировнного имени функции ('A::F()'), т.е. Comeau и GCC по-прежнему будут ругаться.
Best regards,
Андрей Тарасевич
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.