← Назад к вопросам

Есть ли в C++ интерфейс?

2.0 Middle🔥 131 комментариев
#ООП и проектирование#Язык C++

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Интерфейсы в C++

С++ не имеет явной ключевой слова interface, как в Java или C#. Однако, концепция интерфейса существует и реализуется через абстрактные классы с чистыми виртуальными методами (pure virtual methods).

Абстрактный класс как интерфейс

Абстрактный класс — это класс, который содержит хотя бы один чистый виртуальный метод (pure virtual method). Такой класс нельзя инстанцировать, его можно только использовать как базовый класс для наследования.

// Определяем интерфейс как абстрактный класс
class IAnimal {
public:
    virtual ~IAnimal() = default;  // Виртуальный деструктор
    
    // Чистые виртуальные методы
    virtual void speak() const = 0;
    virtual void move() const = 0;
    virtual std::string get_name() const = 0;
};

// Нельзя так сделать!
// IAnimal animal;  // Ошибка! Абстрактный класс

Реализация интерфейса (наследование)

class Dog : public IAnimal {
private:
    std::string name;
    
public:
    Dog(const std::string& n) : name(n) {}
    
    // Реализуем все методы интерфейса
    void speak() const override {
        std::cout << name << " says: Woof!" << std::endl;
    }
    
    void move() const override {
        std::cout << name << " runs on four legs" << std::endl;
    }
    
    std::string get_name() const override {
        return name;
    }
};

class Bird : public IAnimal {
private:
    std::string name;
    
public:
    Bird(const std::string& n) : name(n) {}
    
    void speak() const override {
        std::cout << name << " says: Tweet!" << std::endl;
    }
    
    void move() const override {
        std::cout << name << " flies in the sky" << std::endl;
    }
    
    std::string get_name() const override {
        return name;
    }
};

Использование интерфейса (полиморфизм)

int main() {
    // Используем указатели или ссылки на интерфейс
    std::vector<std::unique_ptr<IAnimal>> animals;
    
    animals.push_back(std::make_unique<Dog>("Rex"));
    animals.push_back(std::make_unique<Bird>("Tweety"));
    animals.push_back(std::make_unique<Dog>("Max"));
    
    // Полиморфизм: каждый животное говорит и движется по-своему
    for (const auto& animal : animals) {
        animal->speak();
        animal->move();
        std::cout << "---" << std::endl;
    }
    
    return 0;
}

// Вывод:
// Rex says: Woof!
// Rex runs on four legs
// ---
// Tweety says: Tweet!
// Tweety flies in the sky
// ---
// Max says: Woof!
// Max runs on four legs
// ---

Виртуальные методы и полиморфизм

Ключевое слово virtual означает, что метод может быть переопределён в производном классе. override (C++11) явно указывает, что мы переопределяем метод базового класса.

class Shape {
public:
    virtual ~Shape() = default;  // ВАЖНО! Всегда виртуальный деструктор
    virtual double area() const = 0;       // Чистый виртуальный
    virtual void draw() const = 0;
};

class Circle : public Shape {
private:
    double radius;
    
public:
    Circle(double r) : radius(r) {}
    
    double area() const override {
        return 3.14159 * radius * radius;
    }
    
    void draw() const override {
        std::cout << "Drawing circle with radius " << radius << std::endl;
    }
};

class Rectangle : public Shape {
private:
    double width, height;
    
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    
    double area() const override {
        return width * height;
    }
    
    void draw() const override {
        std::cout << "Drawing rectangle " << width << "x" << height << std::endl;
    }
};

Важные правила

1. Виртуальный деструктор

class IBase {
public:
    virtual ~IBase() = default;  // ОБЯЗАТЕЛЬНО!
    virtual void do_something() = 0;
};

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

int main() {
    IBase* ptr = new Dog("Rex");
    delete ptr;  // Без virtual деструктора — утечка памяти!
}

2. Использование override (C++11)

class Base {
public:
    virtual void method() {}
};

class Derived : public Base {
public:
    void method() override {}  // Явно указываем переопределение
    // void metod() override {}  // Ошибка на этапе компиляции!
};

3. Абстрактный класс со всеми чистыми методами (100% интерфейс)

class IDatabase {
public:
    virtual ~IDatabase() = default;
    virtual bool connect(const std::string& url) = 0;
    virtual void disconnect() = 0;
    virtual bool execute_query(const std::string& query) = 0;
    virtual std::vector<std::string> fetch_results() = 0;
};

Классификация интерфейсов в C++

Интерфейс только (как в Java interface):

  • Только чистые виртуальные методы
  • Нет членов данных
  • Нет реализации

Абстрактный класс:

  • Смесь чистых виртуальных и обычных методов
  • Может иметь реализацию по умолчанию
  • Может иметь члены данных

Альтернатива: Шаблон Template Method

class DataProcessor {
public:
    virtual ~DataProcessor() = default;
    
    // Template method
    void process(const std::vector<int>& data) {
        validate(data);
        transform(data);
        save(data);
    }
    
private:
    virtual void validate(const std::vector<int>& data) = 0;
    virtual void transform(const std::vector<int>& data) = 0;
    virtual void save(const std::vector<int>& data) = 0;
};

Итог

В C++ нет ключевого слова interface, но абстрактные классы с чистыми виртуальными методами выполняют ту же роль. Это позволяет определить контракт (API), который должны реализовать все производные классы. Правильное использование интерфейсов — основа объектно-ориентированного дизайна в C++.

Есть ли в C++ интерфейс? | PrepBro