基类职责过多应立即拆分而非重构。典型信号包括:show()混杂输出/日志/校验;构造函数参数超5个且含非初始化依赖;派生类重写update需强制调用基类并补分支;头文件过度包含第三方库。按SRP拆分为状态管理、行为实现(策略类)、展示逻辑(渲染器)三部分,采用组合替代继承。

基类职责过多,直接拆——不是重构,是止损。继续往里塞逻辑,后续每改一处都得查三遍继承链,gdb 跟进到第 7 层虚函数调用时,连自己写的注释都认不出来了。
先识别「职责混杂」的典型信号
别等编译报错才动手。以下现象出现任意一条,说明基类已经超载:
-
show()函数里既要格式化输出,又要触发日志上报,还得校验数据合法性 - 构造函数参数超过 5 个,且其中包含
std::shared_ptr<DatabaseWriter>和std::function<void()>这类明显不属于“初始化本体”的依赖 - 派生类重写
update()时,必须先调用Base::update(),再手动补一堆if (type == X) doY();分支逻辑 - 头文件里
#include了<sqlite3.h>、<curl/curl.h>、<opencv2/opencv.hpp>—— 它早就不只是“交通工具”了,它是个“带轮子的云服务终端”
按 SRP 拆:每个类只管一件事,且这件事能被一句话说清
拿常见的 vehicle 基类为例,它本该只回答“我是什么、我当前状态如何”,但现实中常被塞进三类责任:
-
状态管理:维护
speed、wheels、weight—— 留在基类,但仅限于存储和基础访问(get_speed()) -
行为实现:比如
accelerate()里调用了物理引擎接口、又写了数据库快照 —— 这些全移出去,做成独立策略类,如PhysicsEngineAdapter、TelemetryLogger -
展示逻辑:格式化字符串、生成 HTML、调用 UI 组件 —— 提取为
VehicleRenderer或VehicleFormatter,由外部注入或组合使用
拆完后,car 类不再继承一个“全能基类”,而是:
立即学习“C++免费学习笔记(深入)”;
class car : public vehicle {
PhysicsEngineAdapter physics_;
TelemetryLogger logger_;
VehicleRenderer renderer_;
public:
car(PhysicsEngineAdapter p, TelemetryLogger l, VehicleRenderer r)
: vehicle(80, 4, 1000), physics_(p), logger_(l), renderer_(r) {}
};
警惕「伪拆分」:把 if-else 搬到工厂里不算解耦
有人会把大基类里的分支逻辑挪进工厂类的 create() 方法里,比如:
if (type == "boat") return new boat(...); else if (type == "truck") return new truck(...);
这没解决根本问题——boat 和 truck 仍各自背负着 IO、渲染、校验等多份职责。真正的拆分发生在类内部:让 boat 只关心浮力计算与吃水线更新,其余交由组合对象完成。
虚继承、模板特化、PIMPL 这些技巧,在职责不清的前提下强行使用,只会把问题从“一个类太胖”变成“五个类互相拉扯”。先理清「谁该做什么」,再选工具。
最难的不是写新类,是说服自己删掉基类里那行写了十年的注释:// TODO: 抽离日志部分(勿动!) —— 它早就不是 TODO,是遗嘱。


















