如何确保类仅从预定义的派生类集合中继承?
嘿,这个需求我之前也碰到过类似的——要让Derived3只能从你指定的Derived1/Derived2继承,不能直接碰Base或者其他无关类对吧?这里给你两个实用的方案,分两种场景来讨论:
方案1:修改原有类,用Protected构造+友元严格控制权限
如果Base、Derived1、Derived2的代码是你能修改的,这是最优雅的方案:通过把构造函数设为protected,再配合友元限制,从根源上杜绝非法继承。
// 修改Base的构造为protected,禁止直接继承它 class Base { protected: Base() = default; public: virtual void fun() = 0; // 改成纯虚函数更合理,毕竟所有派生类都要重写它 private: int variable; }; // 修改Derived1:构造设为protected,只让Derived3成为友元 class Derived1 : public Base { friend class Derived3; // 只有Derived3能继承我 protected: Derived1() = default; public: virtual void fun() override {} virtual void moreFun() {} private: int variable; }; // Derived2的修改和Derived1完全一致 class Derived2 : public Base { friend class Derived3; protected: Derived2() = default; public: virtual void fun() override {} virtual void moreFun() {} private: int variable; }; // 现在Derived3只能合法继承Derived1/Derived2 class Derived3 : public Derived1 { public: Derived3() = default; // 因为是Derived1的友元,能访问protected构造 }; // 以下写法都会编译报错,完美拦截非法继承: // class Derived4 : public Derived1 {}; // Derived4不是Derived1的友元,无法访问protected构造 // class Derived5 : public Base {}; // Base的构造是protected,无法直接继承
方案2:不修改原有类,用模板+静态断言做编译期检查
如果Base、Derived1、Derived2是不能修改的(比如来自第三方库),那我们可以用编译期静态断言来做检查,同样能在编译阶段就拦截非法继承。
// 原有类完全保持不变,不需要任何修改 class Base { public: virtual void fun() {} private: int variable; }; class Derived1 : public Base { public: virtual void fun() override {} virtual void moreFun() {} private: int variable; }; class Derived2 : public Base { public: virtual void fun() override {} virtual void moreFun() {} private: int variable; }; // 定义一个辅助模板类,用于做继承合法性检查 template<typename AllowedBase> class RestrictInheritance { // 静态断言:只允许AllowedBase是Derived1或Derived2 static_assert(std::is_same_v<AllowedBase, Derived1> || std::is_same_v<AllowedBase, Derived2>, "Error: Derived3 can only inherit from Derived1 or Derived2!"); protected: RestrictInheritance() = default; // 保护构造,只允许派生类访问 }; // 用模板包装一层,让Derived3通过它来继承合法基类 template<typename AllowedBase> class LegitimateDerived : public AllowedBase, private RestrictInheritance<AllowedBase> { public: using AllowedBase::AllowedBase; // 继承合法基类的构造函数 }; // 合法用法:指定继承Derived1 class Derived3 : public LegitimateDerived<Derived1> { public: Derived3() = default; }; // 以下写法会触发编译错误: // class Derived4 : public LegitimateDerived<Base> {}; // 触发静态断言,提示非法基类
这个方案的好处是完全不影响原有代码,而且是编译期检查,不会带来任何运行时开销。
内容的提问来源于stack exchange,提问作者EV_A
相关产品推荐
相关产品推荐

