"ComeauTest.c", line 3: warning: call of pure virtual function
~A() { F(); }
^
Ага, а тут это всего лишь сообщение. Но дальше больше. VC 7.0. Компилируем, все хорошо (может какую то галочку забыл нажать в свойствах компиляции?). А вот линкер ругаеться, говорит:
C> ...
C>Ага, а тут это всего лишь сообщение. Но дальше больше. VC 7.0. Компилируем, все хорошо (может какую то галочку забыл нажать в свойствах компиляции?). А вот линкер ругаеться, говорит: C>
C>Спрашиваеться, а почему линкер ищет эту абстрактную функцию? Я понял бы другое сообщения об ошибке, но не такое.
Потому что компилятор соображает, что вызов виртуальной функции 'F()' (как и любой другой виртуальной функции) из деструктора класса 'A' совсем не обязательно делать виртуально. Так как уже на стадии компиляции соврешенно ясно, что вызваться будет именно функция 'A::F()', компилятор в целях оптимизации генерирует прямой (невиртуальный) вызов именно функции 'A::F()' из деструктора класса 'A', взваливая задачу связывания этого вызова на хрупкие плечи линкера. Линкер, разумеется, связать этот вызов не может, ибо тела у функции 'A::F()' нет. Отсюда и сообщение об ошибке.
Я думаю, что если бы ты добавил в свой код определение функции 'A::F()', то VC7.0 молча бы скомпилировал этот код.
Правда легальным от этого данный код бы не стал все равно, ибо такие pure virtual функии разрешается вызвать только при помощи указания полностью квалифицировнного имени функции ('A::F()'), т.е. Comeau и GCC по-прежнему будут ругаться.
Best regards,
Андрей Тарасевич
Re[2]: Вызов виртуальной функции в деструкторе (VC 7.0)
Здравствуйте, Андрей Тарасевич, Вы писали:
C>>Спрашиваеться, а почему линкер ищет эту абстрактную функцию? Я понял бы другое сообщения об ошибке, но не такое.
АТ>...
Спасибо, разобрался. А разобрался не в том что можно или нет использовать виртульные функции в деструкторе, с этим все понятно. Я просто не думал что можно определять тело абстрактной функции. Никогда не пользовался этой возможностью, думаю что и не буду.
C>Спасибо, разобрался. А разобрался не в том что можно или нет использовать виртульные функции в деструкторе, с этим все понятно. Я просто не думал что можно определять тело абстрактной функции. Никогда не пользовался этой возможностью, думаю что и не буду.
Это бывает полезно. Например, если мы создаем класс, не предназначенный для прямого использования (то есть, абстрактный), но при этом логика его архитектуры такова, что чисто виртуальных функций в нем нет, то чем вводить лишнюю ЧВФ только для придания классу статуса "абстрактного", имеет смысл сделать чисто виртуальным деструктор. При этом мы обязаны предоставить определение такого деструктора, ибо он все равно будет вызываться неявно, из деструктора потомка.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Вызов виртуальной функции в деструкторе (VC 7.0)
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Правда легальным от этого данный код бы не стал все равно, ибо такие pure virtual функции разрешается вызвать только при помощи указания полностью квалифицированного имени функции ('A::F()'), т.е. Comeau и GCC по-прежнему будут ругаться.
Буду очень благодарен, если укажешь пункт Стандарта, в соответствии с которым MSVC не прав.
Re[3]: Вызов виртуальной функции в деструкторе (VC 7.0)
Здравствуйте, dupamid, Вы писали:
АТ>>Правда легальным от этого данный код бы не стал все равно, ибо такие pure virtual функции разрешается вызвать только при помощи указания полностью квалифицированного имени функции ('A::F()'), т.е. Comeau и GCC по-прежнему будут ругаться.
D>Буду очень благодарен, если укажешь пункт Стандарта, в соответствии с которым MSVC не прав.
Согласно 10.4/6, попытка выполнения виртуального вызова pure виртуальной функции приводит к неопределенному поведению.
К сожалению, я не нашел прямого определения "виртуального вызова" в стандарте. Но зато в 10.3/12 сказано, что использование полностью квалифицированного имени функции подавляет механизм виртуальных вызовов. Отсюда я делаю вывод, что все вызовы виртуальных функций, которые сделаны не через полностью квалифицированное именя, являются виртуальными. Таким образом, вызов из деструктора в исходном примере является виртуальным и приводит к неопределенному поведению.
Строго говоря, стандарт не говорит, что такая программа является ill-formed. Она приводит к неопределенному поведению, но компилироваться тем не менее должна, если я ничего не упустил. С этой точки зрения, MSVC++ не прав в том, что отказался компилировать программу. А Comeau с GCC формально правы, ибо они ограничились только предуперждениями.
Best regards,
Андрей Тарасевич
Re[4]: Вызов виртуальной функции в деструкторе (VC 7.0)
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>>>Правда легальным от этого данный код бы не стал все равно, ибо такие pure virtual функции разрешается вызвать только при помощи указания полностью квалифицированного имени функции ('A::F()'), т.е. Comeau и GCC по-прежнему будут ругаться.
D>>Буду очень благодарен, если укажешь пункт Стандарта, в соответствии с которым MSVC не прав.
АТ>Согласно 10.4/6, попытка выполнения виртуального вызова pure виртуальной функции приводит к неопределенному поведению.
АТ>К сожалению, я не нашел прямого определения "виртуального вызова" в стандарте. Но зато в 10.3/12 сказано, что использование полностью квалифицированного имени функции подавляет механизм виртуальных вызовов. Отсюда я делаю вывод, что все вызовы виртуальных функций, которые сделаны не через полностью квалифицированное именя, являются виртуальными. Таким образом, вызов из деструктора в исходном примере является виртуальным и приводит к неопределенному поведению.
АТ>Строго говоря, стандарт не говорит, что такая программа является ill-formed. Она приводит к неопределенному поведению, но компилироваться тем не менее должна, если я ничего не упустил. С этой точки зрения, MSVC++ не прав в том, что отказался компилировать программу. А Comeau с GCC формально правы, ибо они ограничились только предуперждениями.
Что-то тут напутано... GCC дал ошибку, Comeau предупреждение, но он только компилирует, так что мог выдать ошибку на линкере, а MSVC дал ошибку на линкере (если я правильно понял автора топика). По-моему все три варианта допустимы и соответствуют Стандарту, но писать такие программы не следует, так как нельзя положиться на какое-то конкретное поведение компилятора. Во всяком случае, мне не известно пункта Стандарта регламентирующего что именно делать в этой ситуации.
Re[5]: Вызов виртуальной функции в деструкторе (VC 7.0)
Здравствуйте, dupamid, Вы писали:
АТ>>Согласно 10.4/6, попытка выполнения виртуального вызова pure виртуальной функции приводит к неопределенному поведению.
АТ>>К сожалению, я не нашел прямого определения "виртуального вызова" в стандарте. Но зато в 10.3/12 сказано, что использование полностью квалифицированного имени функции подавляет механизм виртуальных вызовов. Отсюда я делаю вывод, что все вызовы виртуальных функций, которые сделаны не через полностью квалифицированное именя, являются виртуальными. Таким образом, вызов из деструктора в исходном примере является виртуальным и приводит к неопределенному поведению.
АТ>>Строго говоря, стандарт не говорит, что такая программа является ill-formed. Она приводит к неопределенному поведению, но компилироваться тем не менее должна, если я ничего не упустил. С этой точки зрения, MSVC++ не прав в том, что отказался компилировать программу. А Comeau с GCC формально правы, ибо они ограничились только предуперждениями.
D>Что-то тут напутано... GCC дал ошибку, Comeau предупреждение, но он только компилирует, так что мог выдать ошибку на линкере, а MSVC дал ошибку на линкере (если я правильно понял автора топика).
А, ОК, я не заметил, что GCC дал именно ошибку. Т.е. он с этой точки зрения тоже "не прав".
Надо бы еще порыться в TC. Может там что-то поменяли касательно этого вопроса.
D>По-моему все три варианта допустимы и соответствуют Стандарту, но писать такие программы не следует, так как нельзя положиться на какое-то конкретное поведение компилятора. Во всяком случае, мне не известно пункта Стандарта регламентирующего что именно делать в этой ситуации.
Писать такие программы, разумеется, не следует. Ибо такой вызов, даже если он скомпилируется, порождает неопределенное поведение.
Best regards,
Андрей Тарасевич
Re[4]: Вызов виртуальной функции в деструкторе (VC 7.0)
Здравствуйте, Андрей Тарасевич, Вы писали:
D>> Буду очень благодарен, если укажешь пункт Стандарта, в соответствии с которым MSVC не прав.
АТ> Согласно 10.4/6, попытка выполнения виртуального вызова pure АТ> виртуальной функции приводит к неопределенному поведению.
Ну да, максимум что есть в этом отношении — ссылка на 10.3 в местах, где упоминается virtual function call.
АТ> Строго говоря, стандарт не говорит, что такая программа является ill-formed. Она приводит АТ> к неопределенному поведению, но компилироваться тем не менее должна, если я ничего не упустил.
Вообще-то, у меня ощущение, что определение undefined behavior (1.3.12) специально допускает завершение
трансляции как проявления неопределенного поведения в целях предоставления возможности ранней диагностики.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен