Действительно ли компилятор обеспечивает реализацию чистого виртуального деструктора?
Чтобы проверить утверждение "компилятор и компоновщик обеспечивают существование тела функции для чистого виртуального деструктора." Из этой статьи geeksforgeeks, я скомпилировал этот код:
class Base
{
public:
virtual ~Base()=0; // Pure virtual destructor
};
class Derived : public Base
{
public:
~Derived()
{
std::cout << "~Derived() is executed";
}
};
int main()
{
//Derived d; <<<
return 0;
}
который скомпилирован без каких-либо ошибок. Так почему же в этом случае компилятор не решил обеспечить существование тела функции?
2 ответа
Потому что компилятор (фактически весь процесс перевода) не должен ничего применять, если вы выполняете нарушение ODR 1. В соответствии со стандартом C++ в [basic.def.odr / 4]:
Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе в виде odr; Диагностика не требуется. Определение может явным образом появиться в программе, оно может быть найдено в стандартной или пользовательской библиотеке или (при необходимости) неявно определено (см. [Class.ctor], [class.dtor] и [class.copy). ]). Встроенная функция должна быть определена в каждой единице перевода, в которой она используется odr.
Компилятор вполне вправе выяснить, что ваша программа на самом деле не использует деструктор 2 Derived
(и, следовательно, деструктор Base
), и просто не удосужился уведомить вас.
1 п е д е л е н и е в л е н и е
2 Что означает "использовать ODR"?
Действительно ли компилятор обеспечивает реализацию чистого виртуального деструктора?
Нет, компилятор не делает ничего подобного.
Компилятор компилирует модули компиляции в объектные файлы, поэтому
скомпилирован без ошибок.
Я думаю, что почти каждый компилятор скомпилирует это безо всякой ошибки. Но компоновщик будет жаловаться. Компилятор просто добавляет код в объектные файлы, а также входящие и исходящие ссылки, которые связаны компоновщиком (для статической компоновки).
Конечно, программа не будет ссылаться, если вы прокомментируете в строке Derived d;
снова, посмотрите онлайн демо.
Обновить
То, что вы показываете в своем вопросе, это просто единица компиляции, если вы связываете это как программу, компоновщик, вероятно, удалит неиспользованный код. Ответ StorryTeller говорит об этом многое.
Если вы прокомментируете в Derived
использовать в основном и скопировать определение Base
Класс в другой модуль компиляции и добавьте реализацию деструктора, вы увидите, что оба будут связаны друг с другом, и результирующая программа будет работать без каких-либо ошибок. Самому компилятору все равно, включаете ли вы определения из заголовков или нет. Я не предлагаю делать это для продуктивного программирования, но чтобы понять, почему компилятор традиционно не заботится о полноте определений. Большинство реальных блоков компиляции часто являются неполными.