CppCoreGuidelines C.120 用类层级表示具有层级继承结构的概念
05 December 2022
C.120: Use class hierarchies to represent concepts with inherent hierarchical structure (only)
理由
在代码中直接表达设计思想,更容易理解和维护。请确保基类所表达的思想,保持在继承类中一致,并且没有其他更好的方式表达这种紧耦合的继承。
如果使用成员数据可以实现相同的目的,就不要使用继承。这种情况下,通常在继承类中,会重载基类的虚函数,或访问受保护的基类成员数据。
例子
class DrawableUIElement { public: virtual void render() const = 0; // ... }; class AbstractButton : public DrawableUIElement { public: virtual void onClick() = 0; // ... }; class PushButton : public AbstractButton { void render() const override; void onClick() override; // ... }; class Checkbox : public AbstractButton { // ... };
例子
不要用类继承层级来表达非层级领域的概念。
template<typename T> class Container { public: // list operations: virtual T& get() = 0; virtual void put(T&) = 0; virtual void insert(Position) = 0; // ... // vector operations: virtual T& operator[](int) = 0; virtual void sort() = 0; // ... // tree operations: virtual void balance() = 0; // ... };
此处,很多继承类无法很好实现这些接口函数。因此基类成了实现过程的负担。更进一步, Container
的用户无法依靠成员函数高效地执行某些操作。还可能会抛出异常。因此用户要依靠运行时检查或者干脆不使用这些过于通用的接口,转而利用运行时类型查询来调用特定的接口(比如dynamic_cast
)。
强化
- 查看是否存在这种情况:类有很多成员,并且这些成员函数什么也不做,只是抛出异常。
- 标记非公开的基类 B 的子类 D 没有重载 B 中的虚函数或者会访问 B 中的保护成员。并且 B 不是以下类型:空类,D 的模板参数,D 的模板实例化。