Действительно ли компилятор обеспечивает реализацию чистого виртуального деструктора?

Чтобы проверить утверждение "компилятор и компоновщик обеспечивают существование тела функции для чистого виртуального деструктора." Из этой статьи 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 Класс в другой модуль компиляции и добавьте реализацию деструктора, вы увидите, что оба будут связаны друг с другом, и результирующая программа будет работать без каких-либо ошибок. Самому компилятору все равно, включаете ли вы определения из заголовков или нет. Я не предлагаю делать это для продуктивного программирования, но чтобы понять, почему компилятор традиционно не заботится о полноте определений. Большинство реальных блоков компиляции часто являются неполными.

Другие вопросы по тегам