2017-01-27 7 views
-2

В C++ мы можем отлично объявить функцию в файле заголовка, не выполнив ее. Это компилируется отлично, и обычно это не создает никаких проблем, однако ... Мне интересно, может ли это вызвать проблему, когда виртуальный деструктор не реализован.Что происходит, когда виртуальные деструкторы объявлены, но не имеют реализации?

Когда виртуальный деструктор не реализован и когда в этом случае мы удалим экземпляр производного класса с помощью указателя базового класса, будет ли вызываться деструктор производного класса?

E.g.

class Base{ 
public: 
    virtual ~Base() {} 
}; 

class Derived: public Base { 
public: 
    ~Derived(); // HAS NO IMPLEMENTATION 
}; 

Base *b = new Derived(); 
delete b; 

Примечание: Как было отмечено в комментарии, приведенный выше пример не связывает ПРАВИЛЬНО. Здесь приводится объяснение ситуации, в которой я пытаюсь получить больше информации, однако на практике во время процесса связывания этот пример приведет к ошибке undefined reference to Derived.

+0

_In C++ мы можем отлично объявить функцию в файле заголовка, не выполняя ее. Это компилируется отлично, и обычно это не создает никаких проблем. Только если вы его не назовете. В противном случае вы получите ошибку компоновщика. Как и в вашем примере. –

+0

Этот комментарий, вероятно, просто пересек обновление, которое я сделал для кода, обратите внимание, что я изменил деструктор базы, которая будет реализована, и деструктор Derived не будет реализован. – Gio

+2

Вы на самом деле ** попробовали ** свой код? Вы должны получить ошибку компоновщика, например 'undefined reference to' Derived :: ~ Derived() ''. –

ответ

4

Что происходит, когда виртуальные деструкторы объявлены, но не имеют реализации?

Если деструктор когда-либо называется (например, в вашем примере), программа нарушает одно правило определения и поэтому плохо сформирована. Стандарт не требует диагностики, и компилятор не сможет сказать, что что-то не так. Но, к счастью, вы, вероятно, будете спасены ошибкой компоновщика.

В C++ мы можем отлично объявить функцию в заголовочном файле, фактически не реализуя ее.

Это правда. Но мы не можем назвать такие функции.


виртуальный и деструктор не очень отношение к вопросу. Эти правила применяются ко всем функциям.

+0

Действительно ли это нарушает ODR? ODR буквально говорит * «Никакая единица перевода не должна содержать более одного определения любой переменной, функции, типа класса, типа перечисления или шаблона». * Поэтому, если существует> 1 определение, ODR нарушается. Если есть 0 определений, нарушается ODR. –

+2

@ChristianHackl раздел ODR довольно большой и не ограничивается первым абзацем :) * «Каждая программа должна содержать ** точно одно определение ** каждой не-встроенной функции или переменной, которая используется odr в этой программе; no требуется диагностика ». * – user2079303

+0

Правда. Это пункт 4. Мне никогда не приходило в голову, что ОДР в основном состоит в том, что формально требует определения определений. –

6

Если вы когда-либо звоните ~Derived() (например, удалив b), вы получите ошибки связывания, поскольку символы для деструктора не существуют. Поскольку ~Base() является виртуальным, ~Derived() будет по-прежнему (попытаться) вызываться при удалении b. Отсутствие реализации не имеет к этому отношения.

+0

Резко видно, я обновил вопрос с этой информацией. – Gio

 Смежные вопросы

  • Нет связанных вопросов^_^