C++如何限制新增子类仅继承FocusedBase而非Base类
实现方案
这里有两种编译期即可生效的零开销方案,均不需要修改现有调用侧和FocusedBase子类的实现逻辑:
方案1:私有构造+友元授权
将Base的构造函数设为私有,仅授权FocusedBase模板类可访问Base的构造函数,其他类直接继承Base时会因无法调用父类构造函数直接编译报错。
代码示例
class BigType {/* 原有实现 */}; // 前置声明FocusedBase模板 template <typename T> class FocusedBase; class Base { // 核心:授予所有FocusedBase实例化类访问Base私有成员的权限 template <typename T> friend class FocusedBase; // 可选:兼容存量旧子类,将已有的直接继承Base的子类也加入友元列表 // friend class OldLegacySubClass; private: // 构造函数私有,外部类无法直接调用 Base() = default; public: virtual int DoStuff(BigType input) = 0; virtual ~Base() = default; }; template <typename SmallType> class FocusedBase : public Base { public: // FocusedBase作为友元可正常调用Base的私有构造 FocusedBase() = default; int DoStuff(BigType input) override final { // 原有BigType转SmallType逻辑 SmallType smallInput = ConvertBigToSmall(input); return DoStuff(smallInput); } virtual int DoStuff(SmallType input) = 0; };
优势
- 实现最简单,100%编译期校验,无任何运行时开销
- 迁移完成后删除旧子类的友元声明,即可彻底禁止所有直接继承Base的行为
方案2:细粒度权限管控(私有继承标记)
如果不希望将Base的所有私有成员都开放给FocusedBase,可以通过私有标记类的方式仅开放构造权限,权限管控更严谨。
代码示例
class BigType {/* 原有实现 */}; class Base { protected: // 继承许可标记类,仅友元可创建实例 struct InheritPermit { friend class FocusedBase; // 可选:兼容旧子类,也把旧子类加为InheritPermit的友元 // friend class OldLegacySubClass; private: InheritPermit() = default; }; public: // 构造必须传入许可标记 explicit Base(InheritPermit) {} virtual int DoStuff(BigType input) = 0; virtual ~Base() = default; }; template <typename SmallType> class FocusedBase : public Base { public: // FocusedBase作为友元可创建许可标记,正常构造Base FocusedBase() : Base(InheritPermit()) {} int DoStuff(BigType input) override final { SmallType smallInput = ConvertBigToSmall(input); return DoStuff(smallInput); } virtual int DoStuff(SmallType input) = 0; };
优势
- 权限粒度更细,仅开放Base的构造权限给FocusedBase,不会泄露其他私有成员
- 同样是编译期校验,无运行时开销
额外建议
可以给Base类添加[[deprecated("禁止直接继承Base,请继承对应SmallType实例化的FocusedBase")]]注解,即使后续有人修改友元逻辑绕过限制,也会触发编译警告,进一步降低出错概率。
内容的提问来源于stack exchange,提问作者mmking
相关产品推荐
相关产品推荐

