C++如何禁止直接访问Base工厂类,仅允许通过Derived类调用?
问题描述
我有一个应用场景,其中Base是一个模板工厂类,可根据模板参数对创建不同对象,但仅特定(可数无限)的模板参数组合是有效的。每个有效参数组合对应一个(有时是模板化的)Derived工厂类。直接使用Base工厂类容易因选择错误的模板参数而出错。我的问题是:如何阻止消费者直接使用Base工厂类?
我希望编译器拒绝标注“prevent”的代码行,即Base<..>::foo和Base<..>::bar仅能通过Derived<..>访问,不能被消费者直接调用。我曾尝试用virtual实现,但该概念无法自然从非静态场景迁移到静态场景。
代码示例
template<typename T1, typename T2> class Base{ Base()=delete; public: // many public static routines T1 static foo(){ return 1; } T2 static bar(){ return 2; } }; template<typename T1> class Derived: public Base<T1,float>{ // hopefully very little code, or none at all, as of now. }; int main(){ // main is the consumer Base<int,float>::foo(); // prevent Derived<int> ::foo(); // permit }
解决方案
以下两种方案都能实现需求,通过访问权限控制限制Base的直接调用:
方案1:友元限制+私有静态成员
把Base的静态成员设为私有,将合法的Derived模板类声明为Base的友元,确保只有Derived能访问这些成员:
template<typename T1, typename T2> class Base{ Base()=delete; // 将静态成员设为私有,外部无法直接访问 static T1 foo(){ return 1; } static T2 bar(){ return 2; } // 声明模板Derived为友元,覆盖所有实例 template<typename U> friend class Derived; }; template<typename T1> class Derived: public Base<T1,float>{ public: // 显式暴露Base的静态成员,供外部调用 using Base<T1,float>::foo; using Base<T1,float>::bar; }; int main(){ Base<int,float>::foo(); // 编译错误:foo是私有成员 Derived<int>::foo(); // 正常编译:Derived是Base的友元,且公开了接口 }
方案2:保护成员+继承公开
将Base的静态成员设为保护,Derived继承后通过using声明把成员提升为公开,外部只能通过Derived访问:
template<typename T1, typename T2> class Base{ protected: Base()=delete; // 静态成员设为保护,仅子类可访问 static T1 foo(){ return 1; } static T2 bar(){ return 2; } }; template<typename T1> class Derived: public Base<T1,float>{ public: // 将Base的保护静态成员提升为公开 using Base<T1,float>::foo; using Base<T1,float>::bar; }; int main(){ Base<int,float>::foo(); // 编译错误:foo是保护成员,外部无权访问 Derived<int>::foo(); // 正常编译:Derived公开了接口 }
补充说明
- 两种方案均无需虚函数,静态成员本身不支持多态,通过访问权限控制即可解决问题。
- 若存在多个不同的
Derived模板,方案1只需添加对应模板友元声明,方案2只需让新的Derived类继承Base并公开接口即可。
内容的提问来源于stack exchange,提问作者user22056011
相关产品推荐
相关产品推荐

