C++面试题_12_SOLID原则

SOLID 原则(面向对象设计的五条基本准则)

SOLID 是面向对象设计的五条原则组合,有助于提高代码可维护性、可扩展性与可测试性。每条原则都简短明确 —— 下面逐条说明并给出简洁的 C++ 风格示例与常见陷阱。

S — Single Responsibility Principle(单一职责原则)

一句话:一个类应该只有一个引起它变化的原因。
要点:把不同关注点分离到不同类里,避免“上帝类”。

// 坏:Logger 和 数据访问混在一起
class UserRepository {
public:
    User getUser(int id);
    void log(const std::string& msg); // 不属于仓库职责
};

// 好:职责分离
class Logger { public: void log(const std::string&); };
class UserRepository {
    Logger& logger;
public:
    UserRepository(Logger& l): logger(l) {}
    User getUser(int id) { logger.log("getUser"); /*...*/ }
};

常见陷阱:把 UI、业务、持久化、日志等职责堆到一个类里。

O — Open/Closed Principle(开闭原则)

一句话:对扩展开放,对修改关闭 — 新需求通过扩展(继承/组合/策略)实现,而不是改现有代码。
要点:使用抽象接口与多态,避免修改现有类来添加新行为。

struct Shape { virtual double area() const = 0; };
struct Circle : Shape { double r; double area() const override { return 3.14*r*r; } };
struct Rectangle : Shape { double w,h; double area() const override { return w*h; } };

double totalArea(const std::vector<Shape*>& shapes){
    double sum=0; for(auto s: shapes) sum += s->area();
    return sum;
}
// 新增 Triangle 不改 totalArea,符合开闭
常见陷阱:直接在已有类中增加 if/else 分支来处理新类型。

L — Liskov Substitution Principle(里氏替换原则)

一句话:子类应能替换父类且不破坏程序正确性。
要点:子类不能违反父类的契约(行为/前置后置条件、异常语义等)。

class Bird { public: virtual void fly() {} };
class Ostrich : public Bird { 
    // 如果父类假定所有 Bird 都能 fly,Ostrich 就破坏了这个契约
    void fly() override { throw std::runtime_error("can't fly"); }
};
应对方法:重构抽象(把可飞行为抽成 IFlyable 接口),或重新设计继承层次。

I — Interface Segregation Principle(接口隔离原则)

一句话:客户端不应被迫依赖它不使用的方法 —— 用多个小接口替代大接口。
要点:把“胖接口”拆成更小的、角色相关的接口。

struct IPrinter { virtual void print() = 0; virtual void scan() = 0; };
// 若有只打印的设备,被迫实现 scan 就违背了 ISP

struct IPrinter { virtual void print() = 0; };
struct IScanner { virtual void scan() = 0; };

D — Dependency Inversion Principle(依赖倒置原则)

一句话:高层模块不应该依赖低层模块,二者都应该依赖抽象(接口);抽象不应依赖细节,细节应依赖抽象。
要点:通过接口和依赖注入(构造注入/工厂)解耦实现细节。

struct IMessageSender { virtual void send(const std::string&)=0; };
class EmailSender : public IMessageSender { void send(const std::string& m) override {/*...*/} };

class Notification {
    IMessageSender& sender;
public:
    Notification(IMessageSender& s): sender(s) {}
    void notify(const std::string& msg) { sender.send(msg); }
};
// Notification 只依赖 IMessageSender(抽象),不依赖 EmailSender(细节)

实用建议(把原则落地)

  1. 先写小接口、单一职责的类;当代码变化点集中时考虑抽象与分离。

  2. 以测试驱动或模块化重构推动开闭与依赖倒置(引入接口再注入实现)。

  3. 里氏原则常被忽视——重构继承为组合通常更安全。

  4. 不要机械套用 SOLID —— 它们是指导原则,工程中需权衡(过度抽象会增加复杂度)。

  5. 在团队里把 SOLID 与代码审查/PR 规则结合,逐步改进遗留代码。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值