C++三级继承模板Singleton时派生类instance返回Base类型问题解决
问题根因
报错的核心原因是
Derived调用的instance()继承自Base,而Base继承的是SingleTon<Base>特化,因此instance()的返回值固定为Base*类型,自然无法识别Derived类自定义的成员方法。你猜测的「没有实例化SingleTon<Derived>」是完全正确的,Derived没有对应自身类型的单例接口,才会出现这个问题。
修复方案
方案1:CRTP模板继承(推荐)
将Base改造为CRTP模板类,每个派生类继承时传入自身类型,自动实例化对应类型的单例:
// 原有SingleTon模板逻辑不变,补充单例访问控制 template<class T> class SingleTon { public: static T* instance() { return holder().instance; } protected: // 禁用拷贝、移动、公开构造,符合单例设计规则 SingleTon() = default; SingleTon(const SingleTon&) = delete; SingleTon& operator=(const SingleTon&) = delete; ~SingleTon() = default; template<class I> struct Holder { Holder() : instance(new I()) { } I* instance; }; static Holder<T> &holder() { static Holder<T> holder; return holder; } }; // Base改造为模板类 template<class DerivedT> class Base : public SingleTon<DerivedT> { public: Base() = default; void printBase() { std::cout << "Base\n"; } }; // Derived继承时传入自身类型给Base模板 class Derived : public Base<Derived> { public: Derived() = default; void printDerived() { std::cout << "Derived\n"; } }; // main函数无需修改即可正常运行 int main() { Derived::instance()->printBase(); Derived::instance()->printDerived(); // 不再报错 return 0; }
这个方案无需修改原有调用逻辑,派生类天然拥有对应自身类型的单例接口,继承链不会生成多余的单例实例。
方案2:派生类多继承单例(适合不能修改Base定义的场景)
如果不能将Base改造为模板,可以让Derived同时继承Base和对应自身类型的SingleTon,显式声明使用的instance方法:
class Derived : public Base, public SingleTon<Derived> { public: // 显式指定使用SingleTon<Derived>的instance方法,覆盖Base继承来的instance using SingleTon<Derived>::instance; Derived() = default; void printDerived() { std::cout << "Derived\n"; } };
*注意:该方案会同时存在Base和Derived两个独立的单例实例,如果你的业务逻辑要求继承链上只有一个单例实例,不要用这个方案。
内容的提问来源于stack exchange,提问作者RomaFUN
相关产品推荐
相关产品推荐

