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

Почему имеет смысл дать определение чистой виртуальной функции?

Скотт сказал на Effective С++, 3rd Edition, pg. 43 что для создания абстрактного класса нам просто нужно дать ему чистый виртуальный деструктор:

class AWOV {                  // AWOV = "Abstract w/o Virtuals"
public:
  virtual ~AWOV() = 0;        // declare pure virtual destructor
};

Затем он продолжал говорить, что есть один поворот: мы должны предоставить определение для чистого виртуального деструктора:

AWOV::~AWOW() {}              // definition of pure virtual dtor

Мой вопрос состоит в том, что, указав = 0, для чистых виртуальных функций, мы говорим, что функция не может иметь никакого определения для класса, в котором объявлена ​​эта чистая виртуальная функция.

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

4b9b3361

Ответ 1

"мы говорим, что функция не может иметь никакого определения для класса, в котором объявлена ​​эта чистая виртуальная функция.

Это не то, что означает чистый виртуальный. Чистая виртуальная только означает, что содержащий класс не может быть создан (абстрактно), поэтому он должен быть подклассом, а подклассы должны переопределять метод. Например.

struct A {
    virtual ~A() = 0;
};

A::~A() {}

struct B : A {};

int main()
{
    A a;  // error
    B b;  // ok
}

Здесь деструктор B неявно определен. Если это был другой метод, который является чисто виртуальным, вам придется явно переопределить его:

struct A {
    virtual void foo() = 0;
};

void A::foo() {}

struct B : A {};

int main()
{
    B b;  // error
}

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

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

Ответ 2

Создание чистых производных (не абстрактных) классов для реализации своих собственных.

Предоставление реализации позволяет производным классам вызывать поведение базового класса (какие деструкторы выполняют по умолчанию).

Ответ 3

Есть 2 случая.

Чистый виртуальный деструктор

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

12.4 Деструкторы [class.dtor]

9) Деструктор может быть объявлен virtual (10.3) или чистым virtual (10.4); если какие-либо объекты этого класса или любые производный класс создаются в программе, деструктор должен быть определен. Если класс имеет базовый класс с виртуальный деструктор, его деструктор (независимо от того, объявлен ли пользователь или неявно) является виртуальным.

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

Чистый виртуальный метод

Они отличаются от деструкторов тем, что они не требуются для реализации, и им не нужна реализация. Разница в недостающем требовании заключается в том, что при вызове Derived::foo() он автоматически не вызывает Base::foo() (не так, как мог, поскольку он может или не может быть реализован).

Почему вы хотите реализовать чистый метод virtual, зависит от случая. Я рассматриваю чистый спецификатор как намек на программиста, а не на логику. Он сообщает вам - программисту - , что вы должны реализовать этот метод. На самом деле не имеет значения, имеет ли базовый класс реализацию или нет.

by specificiying = 0, для чистых виртуальных функций мы говорим, что функция не может иметь никакого определения для класса, в котором объявлена ​​эта чистая виртуальная функция.

Не совсем. Вы говорите, что производные не-абстрактные классы должны переопределять эту функцию. Это не мешает вам реализовать его самостоятельно.

Ответ 4

Это не обязательно для всех чистых виртуальных функций. Не за что.

Таким образом, производные классы будут по-прежнему вынуждены переопределять реализацию, но в базовом классе будет реализована реализация по умолчанию , если вам нужно ее называть. > . И этот случай здесь - потому что вы имеете дело с деструктором: когда производный объект уничтожается, его деструктор вызывается и вызываются его деструкторы его базовых классов. Для этого вам нужна реализация для A::~A.

Ответ 5

Используя функцию pure virtual, мы вынуждаем пользователя класса заменять функцию другим в производном классе.

Функцию базового класса можно вызвать с помощью BaseClass::myfunction(...)

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