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 = ±
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;
}总结
抽象是软件设计的重要原则,帮助我们构建清晰、可维护的代码架构:
抽象层次
- 概念抽象:隐藏复杂实现,提供简洁接口
- 数据抽象:封装数据和操作
- 行为抽象:定义统一的行为规范
- 创建抽象:工厂模式,创建对象的抽象
实现技术
| 技术 | 用途 | 特点 |
|---|---|---|
| 纯虚函数 | 定义接口 | 强制实现 |
| 抽象基类 | 类层次根部 | 不能实例化 |
| 接口设计 | 行为契约 | 职责单一 |
| 模板 | 泛型抽象 | 编译时决定 |
设计原则
- 单一职责:一个抽象只负责一种职责
- 开闭原则:对扩展开放,对修改关闭
- 里氏替换:子类可以替换父类
- 接口分离:接口应该小而专一
- 依赖倒置:依赖抽象而非具体
抽象让代码更加模块化、可测试和可扩展,是构建大型软件系统的基石。