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

Что такое Абстрактный класс?

1.2 Junior🔥 241 комментариев
#ООП и проектирование#Язык C++

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

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

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

# Что такое Абстрактный класс?

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

Определение

Абстрактный класс — это класс в объектно-ориентированном программировании, который:

  • Содержит хотя бы одну чистую виртуальную функцию
  • Не может быть создан экземпляр (new)
  • Служит как шаблон для производных классов
  • Определяет контракт, который наследники должны выполнить

Синтаксис в C++

Чистая виртуальная функция

class Shape {  // Абстрактный класс
public:
    // Чистая виртуальная функция (= 0)
    virtual void draw() = 0;
    virtual void area() = 0;
    
    // Обычная виртуальная функция (может иметь реализацию)
    virtual ~Shape() {}
};

// ОШИБКА: Shape s;  // Нельзя создать экземпляр абстрактного класса

Реализация в производных классах

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : radius(r) {}
    
    // Обязательно реализовать все чистые виртуальные функции
    void draw() override {
        cout << "Drawing circle" << endl;
    }
    
    void area() override {
        cout << "Area: " << 3.14 * radius * radius << endl;
    }
};

class Rectangle : public Shape {
private:
    double width, height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}
    
    void draw() override {
        cout << "Drawing rectangle" << endl;
    }
    
    void area() override {
        cout << "Area: " << width * height << endl;
    }
};

// Теперь можно создавать экземпляры
Circle c(5);
c.draw();    // Drawing circle
c.area();    // Area: 78.5

Rectangle r(4, 6);
r.draw();    // Drawing rectangle
r.area();    // Area: 24

Частично абстрактный класс

Класс, который реализует некоторые методы, но не все, остаётся абстрактным:

class Animal {
public:
    // Чистая виртуальная функция
    virtual void sound() = 0;
    
    // Имеет реализацию
    virtual void sleep() {
        cout << "Animal is sleeping" << endl;
    }
    
    virtual ~Animal() {}
};

class Dog : public Animal {
public:
    void sound() override {
        cout << "Woof" << endl;
    }
    // sleep() наследуется
};

Dog d;
d.sound();   // Woof
d.sleep();   // Animal is sleeping

Полиморфизм через абстрактный класс

// Функция принимает указатель на базовый абстрактный класс
void processShape(Shape* shape) {
    shape->draw();
    shape->area();
}

int main() {
    Circle circle(3);
    Rectangle rect(4, 5);
    
    processShape(&circle);   // Полиморфное поведение
    processShape(&rect);     // Вызывает правильный метод
    
    return 0;
}

Практический пример: Система баз данных

// Абстрактный класс для работы с БД
class Database {
public:
    virtual bool connect(const std::string& connection) = 0;
    virtual bool query(const std::string& sql) = 0;
    virtual void disconnect() = 0;
    virtual ~Database() {}
};

// Реализация для MySQL
class MySQLDatabase : public Database {
private:
    // MySQL-specific members
    void* connection;

public:
    bool connect(const std::string& connection) override {
        // MySQL connection logic
        cout << "Connected to MySQL" << endl;
        return true;
    }
    
    bool query(const std::string& sql) override {
        cout << "Executing MySQL query: " << sql << endl;
        return true;
    }
    
    void disconnect() override {
        cout << "Disconnected from MySQL" << endl;
    }
};

// Реализация для PostgreSQL
class PostgreSQLDatabase : public Database {
public:
    bool connect(const std::string& connection) override {
        cout << "Connected to PostgreSQL" << endl;
        return true;
    }
    
    bool query(const std::string& sql) override {
        cout << "Executing PostgreSQL query: " << sql << endl;
        return true;
    }
    
    void disconnect() override {
        cout << "Disconnected from PostgreSQL" << endl;
    }
};

// Использование
int main() {
    Database* db;
    
    if (needMySQL) {
        db = new MySQLDatabase();
    } else {
        db = new PostgreSQLDatabase();
    }
    
    db->connect("server=localhost");
    db->query("SELECT * FROM users");
    db->disconnect();
    
    delete db;
    return 0;
}

Интерфейсы (Interface)

Если абстрактный класс содержит ТОЛЬКО чистые виртуальные функции, это называется интерфейсом:

// Интерфейс (interface)
class Drawable {
public:
    virtual void draw() = 0;
    virtual ~Drawable() {}
};

// Интерфейс (interface)
class Resizable {
public:
    virtual void resize(int width, int height) = 0;
    virtual ~Resizable() {}
};

// Класс может реализовать несколько интерфейсов
class Window : public Drawable, public Resizable {
public:
    void draw() override {
        cout << "Drawing window" << endl;
    }
    
    void resize(int width, int height) override {
        cout << "Resizing to " << width << "x" << height << endl;
    }
};

Различия между абстрактными классами и интерфейсами

Абстрактный классИнтерфейс
Может иметь реализованные методыТолько сигнатуры методов
Может иметь protected членыОбычно public-only
Наследование IS-AКонтракт (может быть)
Одно наследованиеМножественное наследование

Практическое применение

1. Разработка на основе контрактов

// Контракт: как должны работать стратегии сортировки
class SortStrategy {
public:
    virtual void sort(std::vector<int>& arr) = 0;
    virtual ~SortStrategy() {}
};

2. Framework разработка

class HTTPHandler {
public:
    virtual Response handle(const Request& req) = 0;
    virtual ~HTTPHandler() {}
};

3. Plugin система

class Plugin {
public:
    virtual void init() = 0;
    virtual void execute() = 0;
    virtual void cleanup() = 0;
    virtual ~Plugin() {}
};

Важные моменты

  1. Деструктор виртуальный: Всегда делайте деструктор виртуальным в абстрактных классах
  2. override: Используйте ключевое слово override для ясности
  3. Чистые виртуальные функции: Нельзя создавать экземпляры класса с ними
  4. Контракт: Абстрактный класс — это контракт между разработчиком интерфейса и разработчиком реализации

Вывод

Абстрактные классы — это мощный инструмент в C++ для:

  • Определения интерфейсов и контрактов
  • Реализации полиморфизма
  • Разработки масштабируемых и расширяемых систем
  • Отделения интерфейса от реализации

Они критичны для написания хорошо спроектированного кода, особенно в backend-системах, где требуется работать с различными компонентами через единый интерфейс.

Что такое Абстрактный класс? | PrepBro