← Назад к вопросам
Что такое чисто виртуальный вызов?
2.7 Senior🔥 71 комментариев
#ООП и проектирование#Язык C++
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Чисто виртуальный вызов (Pure Virtual Function)
Чисто виртуальная функция — это виртуальная функция в базовом классе, которая не имеет реализации и должна быть обязательно переопределена в каждом наследующем классе. Она служит для определения интерфейса.
Синтаксис
class Base {
public:
virtual void pureVirtualMethod() = 0; // Чисто виртуальная
virtual void virtualWithImpl() { // Обычная виртуальная
std::cout << "Base implementation" << std::endl;
}
virtual ~Base() {}
};
Абстрактные классы
Класс с чисто виртуальной функцией — абстрактный класс. Нельзя создать экземпляр:
class Shape {
public:
virtual void draw() = 0;
virtual double area() = 0;
virtual ~Shape() {}
};
Shape shape; // ОШИБКА: абстрактный класс!
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
void draw() override {
std::cout << "Drawing circle" << std::endl;
}
double area() override {
return 3.14159 * radius * radius;
}
};
Полиморфизм
#include <iostream>
#include <vector>
#include <memory>
class Animal {
public:
virtual void sound() = 0;
virtual std::string getName() const = 0;
virtual ~Animal() {}
};
class Dog : public Animal {
public:
void sound() override {
std::cout << "Woof!" << std::endl;
}
std::string getName() const override {
return "Dog";
}
};
class Cat : public Animal {
public:
void sound() override {
std::cout << "Meow!" << std::endl;
}
std::string getName() const override {
return "Cat";
}
};
int main() {
std::vector<std::unique_ptr<Animal>> animals;
animals.push_back(std::make_unique<Dog>());
animals.push_back(std::make_unique<Cat>());
for (auto& animal : animals) {
std::cout << animal->getName() << ": ";
animal->sound(); // Полиморфный вызов
}
return 0;
}
Множественное наследование
class Drawable {
public:
virtual void draw() = 0;
virtual ~Drawable() {}
};
class Serializable {
public:
virtual std::string serialize() = 0;
virtual ~Serializable() {}
};
class Document : public Drawable, public Serializable {
public:
void draw() override {
std::cout << "Drawing document" << std::endl;
}
std::string serialize() override {
return "<document/>";
}
};
Template Method Pattern
class DataProcessor {
public:
void process() {
loadData();
validate();
transform();
save();
}
protected:
virtual void loadData() = 0;
virtual void validate() = 0;
virtual void transform() = 0;
virtual void save() = 0;
virtual ~DataProcessor() {}
};
class CSVProcessor : public DataProcessor {
protected:
void loadData() override { std::cout << "Loading CSV" << std::endl; }
void validate() override { std::cout << "Validating CSV" << std::endl; }
void transform() override { std::cout << "Transforming CSV" << std::endl; }
void save() override { std::cout << "Saving CSV" << std::endl; }
};
Интерфейсы (Interface Pattern)
class ISerializer {
public:
virtual std::string serialize() const = 0;
virtual void deserialize(const std::string& data) = 0;
virtual ~ISerializer() = default;
};
class JSONSerializer : public ISerializer {
public:
std::string serialize() const override {
return "{\"type\": \"json\"}";
}
void deserialize(const std::string& data) override {
// Парсинг JSON
}
};
Ключевые отличия
| Характеристика | Обычная виртуальная | Чисто виртуальная |
|---|---|---|
| Реализация | Имеет | Не имеет (= 0) |
| Создание объектов | Можно | Нельзя |
| Переопределение | Опционально | Обязательно |
| Использование | Переопределяемое поведение | Интерфейс |
Преимущества: контрактное программирование, полиморфизм, разделение интерфейса и реализации, четкая архитектура.