Подтвердить что ты не робот

Определение чистого виртуального деструктора внутри класса дает ошибку компиляции

В базовом классе pure virtual destructor должно быть определение. В противном случае компилятор будет генерировать вызов деструктора базового класса из деструктора производного класса во время ссылки и вызовет ошибку ссылки.

Я попытался определить чистый виртуальный деструктор внутри базового класса, как показано ниже:

class base
{
   public:
      base()
      {
         cout << "constructor in base class\n";
      }

      virtual ~base()=0
      {}
};

Это дало ошибку компиляции:

error: pure-specifier on function-definition

Затем я попытался определить функцию вне базового класса, как показано ниже:

class base
{
   public:
      base()
      {
         cout << "constructor in base class\n";
      }

      virtual ~base()=0;
};

base::~base()
{

}

Это устраняет ошибку компиляции и ведет себя как мое понимание.

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

4b9b3361

Ответ 1

Ваш второй пример правильный.

Многие другие ответы предполагают, что незаконно иметь чистую виртуальную функцию с реализацией по умолчанию, однако это неверно.

В случае чистого виртуального деструктора вы должны иметь определение (см. ссылку в ответе xmoex).

Верно, что:

§10.4/2 объявление функции не может предоставить как чисто-спецификатор и определение

Однако, поскольку вы заметили возможность предоставления определения вне декларации.

Ответ 2

Я просмотрел эту страницу:

http://www.gotw.ca/gotw/031.htm

и из моего понимания чистый виртуальный деструктор должен иметь определение (даже пустое), так как каждый производный класс должен вызывать деструктор базовых классов

Ответ 3

Неправильный синтаксис для записи:

virtual ~base()=0
{}

Если вы хотите предоставить реализацию чистой виртуальной функции-члена, вы должны сделать это за пределами класса. Большую часть времени вы не должны этого делать, поскольку чистые виртуальные функции никогда не должны вызываться так или иначе. Тем не менее, можно определить реализацию для чистых виртуальных функций.

Фактически, чистый виртуальный деструктор должен иметь реализацию. Это связано с тем, что деструкторы всех базовых классов вызываются при уничтожении объекта, независимо от того, является ли деструктор в данном классе чисто виртуальным или нет.

Таким образом, если вы создаете экземпляр любого из классов, полученных из base, то в какой-то момент будут вызваны деструкторы всех классов, к которым принадлежит объект, включая деструктор base::~base(). Если вы не определяете его, компоновщик не найдет требуемый символ и будет жаловаться.

Ответ 4

Деструктор - единственный метод, который даже если он является чисто виртуальным, должен иметь реализацию, чтобы класс, который он определил, был полезен. Поэтому, в отличие от ответа @Kiril, я бы сказал, что чистые виртуальные функции могут иметь реализации.

Немного не в тему:

struct base {
    virtual void func() = 0;
};

void base::func() { /* default implementation */ }

class derived : public base{
    void func() { base::func(); } // have to explicitly call default implementation.
};

Ответ 5

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

Скажите, что у вас есть указатель в базовом классе. Вы хотите удалить его на деструкторе, но также сделать абстрактным класс, поэтому вы реализуете чистый виртуальный деструктор.

Это деталь реализации - тот факт, что деструктор реализован, должен быть видимым снаружи.