Skip to content

C++ 抽象

概述

抽象(Abstraction)是面向对象编程的基本原则之一,它隐藏复杂的实现细节,只向用户展示必要的功能接口。C++通过抽象类、纯虚函数、接口设计等机制实现抽象,帮助开发者构建清晰、可维护的代码架构。

🎭 抽象概念

抽象的本质

cpp
#include <iostream>
#include <string>
#include <memory>

// 抽象:隐藏复杂性,展示简洁接口
class MediaPlayer {
public:
    virtual ~MediaPlayer() = default;
    
    // 抽象接口:用户只需要知道这些操作
    virtual void play() = 0;
    virtual void pause() = 0;
    virtual void stop() = 0;
    virtual void setVolume(int volume) = 0;
    virtual int getVolume() const = 0;
    virtual bool isPlaying() const = 0;
    
    // 公共功能
    void showStatus() const {
        std::cout << "播放器状态: " << (isPlaying() ? "播放中" : "已停止")
                  << ", 音量: " << getVolume() << std::endl;
    }
};

// 具体实现:用户不需要了解内部细节
class MP3Player : public MediaPlayer {
private:
    std::string filename_;
    bool playing_;
    int volume_;
    int position_;  // 播放位置
    
    // 内部复杂操作(抽象隐藏的细节)
    void loadAudioCodec() {
        std::cout << "加载MP3解码器..." << std::endl;
    }
    
    void initializeHardware() {
        std::cout << "初始化音频硬件..." << std::endl;
    }
    
public:
    MP3Player(const std::string& filename) 
        : filename_(filename), playing_(false), volume_(50), position_(0) {
        loadAudioCodec();
        initializeHardware();
    }
    
    // 简洁的外部接口
    void play() override {
        if (!playing_) {
            std::cout << "开始播放: " << filename_ << std::endl;
            playing_ = true;
        }
    }
    
    void pause() override {
        if (playing_) {
            std::cout << "暂停播放" << std::endl;
            playing_ = false;
        }
    }
    
    void stop() override {
        std::cout << "停止播放" << std::endl;
        playing_ = false;
        position_ = 0;
    }
    
    void setVolume(int volume) override {
        volume_ = std::max(0, std::min(100, volume));
        std::cout << "音量设置为: " << volume_ << std::endl;
    }
    
    int getVolume() const override { return volume_; }
    bool isPlaying() const override { return playing_; }
};

int main() {
    std::cout << "=== 抽象概念演示 ===" << std::endl;
    
    // 用户通过抽象接口使用,无需了解内部实现
    std::unique_ptr<MediaPlayer> player = std::make_unique<MP3Player>("song.mp3");
    
    player->play();
    player->setVolume(75);
    player->showStatus();
    
    player->pause();
    player->showStatus();
    
    return 0;
}

🏗️ 抽象类设计

纯虚函数和抽象基类

cpp
#include <iostream>
#include <vector>
#include <memory>

// 抽象基类:定义接口规范
class Database {
public:
    virtual ~Database() = default;
    
    // 纯虚函数定义抽象接口
    virtual bool connect(const std::string& connectionString) = 0;
    virtual void disconnect() = 0;
    virtual bool executeQuery(const std::string& query) = 0;
    virtual std::string getLastError() const = 0;
    
    // 模板方法模式:定义算法骨架
    bool executeTransaction(const std::vector<std::string>& queries) {
        beginTransaction();
        
        for (const auto& query : queries) {
            if (!executeQuery(query)) {
                rollback();
                return false;
            }
        }
        
        return commit();
    }
    
protected:
    // 子类需要实现的钩子方法
    virtual void beginTransaction() = 0;
    virtual bool commit() = 0;
    virtual void rollback() = 0;
};

// MySQL实现
class MySQLDatabase : public Database {
private:
    bool connected_;
    std::string lastError_;
    
public:
    MySQLDatabase() : connected_(false) {}
    
    bool connect(const std::string& connectionString) override {
        std::cout << "连接到MySQL: " << connectionString << std::endl;
        connected_ = true;
        return true;
    }
    
    void disconnect() override {
        if (connected_) {
            std::cout << "断开MySQL连接" << std::endl;
            connected_ = false;
        }
    }
    
    bool executeQuery(const std::string& query) override {
        if (!connected_) {
            lastError_ = "数据库未连接";
            return false;
        }
        
        std::cout << "执行MySQL查询: " << query << std::endl;
        return true;
    }
    
    std::string getLastError() const override {
        return lastError_;
    }
    
protected:
    void beginTransaction() override {
        std::cout << "MySQL: BEGIN TRANSACTION" << std::endl;
    }
    
    bool commit() override {
        std::cout << "MySQL: COMMIT" << std::endl;
        return true;
    }
    
    void rollback() override {
        std::cout << "MySQL: ROLLBACK" << std::endl;
    }
};

// PostgreSQL实现
class PostgreSQLDatabase : public Database {
private:
    bool connected_;
    std::string lastError_;
    
public:
    PostgreSQLDatabase() : connected_(false) {}
    
    bool connect(const std::string& connectionString) override {
        std::cout << "连接到PostgreSQL: " << connectionString << std::endl;
        connected_ = true;
        return true;
    }
    
    void disconnect() override {
        if (connected_) {
            std::cout << "断开PostgreSQL连接" << std::endl;
            connected_ = false;
        }
    }
    
    bool executeQuery(const std::string& query) override {
        if (!connected_) {
            lastError_ = "数据库未连接";
            return false;
        }
        
        std::cout << "执行PostgreSQL查询: " << query << std::endl;
        return true;
    }
    
    std::string getLastError() const override {
        return lastError_;
    }
    
protected:
    void beginTransaction() override {
        std::cout << "PostgreSQL: START TRANSACTION" << std::endl;
    }
    
    bool commit() override {
        std::cout << "PostgreSQL: COMMIT" << std::endl;
        return true;
    }
    
    void rollback() override {
        std::cout << "PostgreSQL: ROLLBACK" << std::endl;
    }
};

int main() {
    std::cout << "=== 抽象类设计 ===" << std::endl;
    
    // 通过抽象接口使用不同的数据库实现
    std::vector<std::unique_ptr<Database>> databases;
    databases.push_back(std::make_unique<MySQLDatabase>());
    databases.push_back(std::make_unique<PostgreSQLDatabase>());
    
    for (auto& db : databases) {
        db->connect("localhost:5432/mydb");
        
        // 执行事务
        std::vector<std::string> queries = {
            "INSERT INTO users VALUES (1, 'Alice')",
            "INSERT INTO users VALUES (2, 'Bob')"
        };
        
        if (db->executeTransaction(queries)) {
            std::cout << "事务执行成功" << std::endl;
        }
        
        db->disconnect();
        std::cout << std::endl;
    }
    
    return 0;
}

🎯 接口设计模式

接口分离原则

cpp
#include <iostream>

// 违反接口分离原则的设计(不好的例子)
class BadWorker {
public:
    virtual ~BadWorker() = default;
    virtual void work() = 0;
    virtual void eat() = 0;
    virtual void sleep() = 0;
    virtual void code() = 0;        // 不是所有工人都会编程
    virtual void manageMeetings() = 0;  // 不是所有工人都管理会议
};

// 遵循接口分离原则的设计
class Worker {
public:
    virtual ~Worker() = default;
    virtual void work() = 0;
};

class Human {
public:
    virtual ~Human() = default;
    virtual void eat() = 0;
    virtual void sleep() = 0;
};

class Programmer {
public:
    virtual ~Programmer() = default;
    virtual void code() = 0;
};

class Manager {
public:
    virtual ~Manager() = default;
    virtual void manageMeetings() = 0;
};

// 具体实现类:只实现需要的接口
class Developer : public Worker, public Human, public Programmer {
private:
    std::string name_;
    
public:
    Developer(const std::string& name) : name_(name) {}
    
    void work() override {
        std::cout << name_ << " 正在工作" << std::endl;
    }
    
    void eat() override {
        std::cout << name_ << " 正在吃饭" << std::endl;
    }
    
    void sleep() override {
        std::cout << name_ << " 正在睡觉" << std::endl;
    }
    
    void code() override {
        std::cout << name_ << " 正在编程" << std::endl;
    }
};

class ProjectManager : public Worker, public Human, public Manager {
private:
    std::string name_;
    
public:
    ProjectManager(const std::string& name) : name_(name) {}
    
    void work() override {
        std::cout << name_ << " 正在管理项目" << std::endl;
    }
    
    void eat() override {
        std::cout << name_ << " 正在吃饭" << std::endl;
    }
    
    void sleep() override {
        std::cout << name_ << " 正在睡觉" << std::endl;
    }
    
    void manageMeetings() override {
        std::cout << name_ << " 正在主持会议" << std::endl;
    }
};

class Robot : public Worker {
private:
    std::string model_;
    
public:
    Robot(const std::string& model) : model_(model) {}
    
    void work() override {
        std::cout << "机器人 " << model_ << " 正在工作" << std::endl;
    }
    // 机器人不需要吃饭和睡觉
};

int main() {
    std::cout << "=== 接口分离原则 ===" << std::endl;
    
    Developer dev("Alice");
    ProjectManager pm("Bob");
    Robot robot("R2D2");
    
    // 通过不同接口访问对象
    Worker* workers[] = {&dev, &pm, &robot};
    
    std::cout << "所有工人开始工作:" << std::endl;
    for (Worker* worker : workers) {
        worker->work();
    }
    
    std::cout << "\n程序员编程:" << std::endl;
    Programmer* programmer = &dev;
    programmer->code();
    
    std::cout << "\n项目经理管理会议:" << std::endl;
    Manager* manager = &pm;
    manager->manageMeetings();
    
    return 0;
}

🏛️ 抽象工厂模式

创建型抽象

cpp
#include <iostream>
#include <memory>

// 抽象产品
class Button {
public:
    virtual ~Button() = default;
    virtual void render() const = 0;
    virtual void onClick() const = 0;
};

class TextField {
public:
    virtual ~TextField() = default;
    virtual void render() const = 0;
    virtual void onInput(const std::string& text) const = 0;
};

// Windows风格产品
class WindowsButton : public Button {
public:
    void render() const override {
        std::cout << "渲染Windows样式按钮" << std::endl;
    }
    
    void onClick() const override {
        std::cout << "Windows按钮点击效果" << std::endl;
    }
};

class WindowsTextField : public TextField {
public:
    void render() const override {
        std::cout << "渲染Windows样式文本框" << std::endl;
    }
    
    void onInput(const std::string& text) const override {
        std::cout << "Windows文本框输入: " << text << std::endl;
    }
};

// Mac风格产品
class MacButton : public Button {
public:
    void render() const override {
        std::cout << "渲染Mac样式按钮" << std::endl;
    }
    
    void onClick() const override {
        std::cout << "Mac按钮点击效果" << std::endl;
    }
};

class MacTextField : public TextField {
public:
    void render() const override {
        std::cout << "渲染Mac样式文本框" << std::endl;
    }
    
    void onInput(const std::string& text) const override {
        std::cout << "Mac文本框输入: " << text << std::endl;
    }
};

// 抽象工厂
class UIFactory {
public:
    virtual ~UIFactory() = default;
    virtual std::unique_ptr<Button> createButton() const = 0;
    virtual std::unique_ptr<TextField> createTextField() const = 0;
};

// 具体工厂
class WindowsFactory : public UIFactory {
public:
    std::unique_ptr<Button> createButton() const override {
        return std::make_unique<WindowsButton>();
    }
    
    std::unique_ptr<TextField> createTextField() const override {
        return std::make_unique<WindowsTextField>();
    }
};

class MacFactory : public UIFactory {
public:
    std::unique_ptr<Button> createButton() const override {
        return std::make_unique<MacButton>();
    }
    
    std::unique_ptr<TextField> createTextField() const override {
        return std::make_unique<MacTextField>();
    }
};

// 客户端代码
class Application {
private:
    std::unique_ptr<UIFactory> factory_;
    
public:
    Application(std::unique_ptr<UIFactory> factory) : factory_(std::move(factory)) {}
    
    void createUI() {
        auto button = factory_->createButton();
        auto textField = factory_->createTextField();
        
        std::cout << "创建UI组件:" << std::endl;
        button->render();
        textField->render();
        
        std::cout << "\n测试交互:" << std::endl;
        button->onClick();
        textField->onInput("Hello World");
    }
};

int main() {
    std::cout << "=== 抽象工厂模式 ===" << std::endl;
    
    // Windows应用
    std::cout << "Windows应用:" << std::endl;
    Application windowsApp(std::make_unique<WindowsFactory>());
    windowsApp.createUI();
    
    std::cout << "\nMac应用:" << std::endl;
    Application macApp(std::make_unique<MacFactory>());
    macApp.createUI();
    
    return 0;
}

📋 抽象设计原则

SOLID原则中的抽象

cpp
#include <iostream>
#include <vector>
#include <memory>

// 依赖倒置原则:高层模块不应该依赖低层模块,都应该依赖抽象
class Logger {
public:
    virtual ~Logger() = default;
    virtual void log(const std::string& message) = 0;
};

class FileLogger : public Logger {
public:
    void log(const std::string& message) override {
        std::cout << "[文件日志] " << message << std::endl;
    }
};

class ConsoleLogger : public Logger {
public:
    void log(const std::string& message) override {
        std::cout << "[控制台] " << message << std::endl;
    }
};

// 开闭原则:对扩展开放,对修改关闭
class NotificationService {
private:
    std::vector<std::shared_ptr<Logger>> loggers_;
    
public:
    void addLogger(std::shared_ptr<Logger> logger) {
        loggers_.push_back(logger);
    }
    
    void sendNotification(const std::string& message) {
        // 业务逻辑
        std::cout << "发送通知: " << message << std::endl;
        
        // 记录日志(依赖抽象,不依赖具体实现)
        for (auto& logger : loggers_) {
            logger->log("通知已发送: " + message);
        }
    }
};

// 里氏替换原则:子类应该能够替换父类
class Shape {
public:
    virtual ~Shape() = default;
    virtual double getArea() const = 0;
    
    // 不变式:面积应该为非负数
    void printArea() const {
        double area = getArea();
        if (area >= 0) {
            std::cout << "面积: " << area << std::endl;
        } else {
            std::cout << "错误:面积不能为负数" << std::endl;
        }
    }
};

class Rectangle : public Shape {
private:
    double width_, height_;
    
public:
    Rectangle(double width, double height) : width_(width), height_(height) {}
    
    double getArea() const override {
        return width_ * height_;  // 满足不变式
    }
};

int main() {
    std::cout << "=== 抽象设计原则 ===" << std::endl;
    
    // 依赖倒置和开闭原则
    NotificationService service;
    service.addLogger(std::make_shared<FileLogger>());
    service.addLogger(std::make_shared<ConsoleLogger>());
    
    service.sendNotification("系统启动完成");
    
    // 里氏替换原则
    std::cout << "\n形状计算:" << std::endl;
    std::unique_ptr<Shape> shape = std::make_unique<Rectangle>(5, 3);
    shape->printArea();
    
    return 0;
}

总结

抽象是软件设计的重要原则,帮助我们构建清晰、可维护的代码架构:

抽象层次

  • 概念抽象:隐藏复杂实现,提供简洁接口
  • 数据抽象:封装数据和操作
  • 行为抽象:定义统一的行为规范
  • 创建抽象:工厂模式,创建对象的抽象

实现技术

技术用途特点
纯虚函数定义接口强制实现
抽象基类类层次根部不能实例化
接口设计行为契约职责单一
模板泛型抽象编译时决定

设计原则

  • 单一职责:一个抽象只负责一种职责
  • 开闭原则:对扩展开放,对修改关闭
  • 里氏替换:子类可以替换父类
  • 接口分离:接口应该小而专一
  • 依赖倒置:依赖抽象而非具体

抽象让代码更加模块化、可测试和可扩展,是构建大型软件系统的基石。

本站内容仅供学习和研究使用。