Что такое чисто виртуальный метод в C++?

Ответ

Чисто виртуальный метод (pure virtual method) — это метод, объявленный в базовом классе с синтаксисом = 0, который не имеет реализации в этом классе. Его цель — определить интерфейс, который обязаны реализовать все производные классы.

class Shape { // Абстрактный базовый класс
public:
    // Чисто виртуальный метод - интерфейс для вычисления площади
    virtual double area() const = 0;

    // Виртуальный деструктор - обязателен для полиморфных базовых классов
    virtual ~Shape() = default;
};

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    // Обязательная реализация чисто виртуального метода
    double area() const override {
        return 3.14159 * radius * radius;
    }
};

Ключевые моменты:

  • Класс, содержащий хотя бы один чисто виртуальный метод, становится абстрактным классом.
  • Нельзя создать экземпляр абстрактного класса: Shape s; // Ошибка компиляции.
  • Производный класс должен переопределить (override) все чисто виртуальные методы, иначе он также останется абстрактным.
  • Чисто виртуальные методы позволяют создавать полиморфные интерфейсы и обеспечивают контракт для наследников.

Ответ 18+ 🔞

Давай разберём эту штуку, а то звучит страшно, а на деле — проще пареной репы. Чисто виртуальный метод — это, грубо говоря, крик базового класса в пустоту: «Эй, наследнички, ёпта, вот эту функцию вы обязаны написать сами, а у меня её нихуя нет!».

В коде это выглядит как virtual double area() const = 0;. Этот нолик после равно — и есть наш волшебный пендель. Он говорит компилятору: «Дружище, тут реализации нет, это просто идея, мечта, интерфейс, блядь».

class Shape { // Это абстрактный базовый класс, его экземпляр создать нельзя
public:
    // Чисто виртуальный метод - интерфейс для вычисления площади
    virtual double area() const = 0;

    // Виртуальный деструктор - обязателен для полиморфных базовых классов
    virtual ~Shape() = default;
};

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    // Обязательная реализация чисто виртуального метода
    double area() const override {
        return 3.14159 * radius * radius;
    }
};

А теперь главное, что нужно уяснить, чтобы не облажаться:

  • Как только ты впихнул в класс хоть один такой метод с = 0, класс сразу становится абстрактным. Это как клеймо. Создать объект этого класса — никак. Shape s; — компилятор тебе тут же впендюрит ошибку, доверия ебать ноль к такой затее.
  • Все детишки (производные классы), которые от него наследуются, обязаны переопределить этот метод. Не захочешь — сам станешь абстрактным, и тебя тоже нельзя будет инстанциировать. Прямо наследование под дулом пистолета, ёб твою мать.
  • А смысл-то в чём? А в том, чтобы задать жёсткий полиморфный интерфейс. Ты говоришь: «Всё, что является Shape, должно уметь считать площадь. А как — это ваши, блядь, проблемы». И потом ты можешь работать с массивом указателей на Shape, вызывать у них area(), и у каждого (круга, квадрата, треугольника-уродца) будет своя реализация. Красота, да и только. Хуй с горы, а не фича.