如何继承魔法静态单例并共享基类单例实例?
问题:魔法静态单例子类共享基类单例实例
原代码
#include <iostream> int main(); class SingletonBase{ protected: int i=0; SingletonBase(int){} // friend int main(); static void show(){ static SingletonBase s(2); // this is sometimes referred to as the "magic static singleton pattern" s.i++; std::cout << "SingletonBase::i="<<s.i<<"\n"; } }; class Singleton: public SingletonBase{ private: Singleton(int):SingletonBase(int{}){} int j=0; // unfortunately, Singleton has data, too. public: static void show(){ static Singleton s(3); s.i++; s.j++; std::cout << "Singleton::SingletonBase::i="<<s.i<<". Singleton::j="<<s.j<<"\n"; } // }; int main() { Singleton::show(); Singleton::show(); Singleton::show(); Singleton::show(); SingletonBase::show(); SingletonBase::show(); SingletonBase::show(); Singleton::show(); Singleton::show(); Singleton::show(); Singleton::show(); }
现有输出
Singleton::SingletonBase::i=1. Singleton::j=1 Singleton::SingletonBase::i=2. Singleton::j=2 Singleton::SingletonBase::i=3. Singleton::j=3 Singleton::SingletonBase::i=4. Singleton::j=4 SingletonBase::i=1 SingletonBase::i=2 SingletonBase::i=3 Singleton::SingletonBase::i=5. Singleton::j=5 Singleton::SingletonBase::i=6. Singleton::j=6 Singleton::SingletonBase::i=7. Singleton::j=7 Singleton::SingletonBase::i=8. Singleton::j=8
需求
希望无论调用Singleton::show()还是SingletonBase::show(),i的值都连续递增,即子类与基类共享同一个单例实例的i,同时子类维护自己的独立状态j。
备注
- 无法取消
main的友元权限 - 实际场景为模板类继承:
ElementA<T>/ElementB<T>继承ElementBase<T>,StackA<T>/StackB<T>继承StackBase<T>,main对应ElementBase<T>(需访问StackBase<T>),SingletonBase对应StackBase<T>,Singleton对应StackA<T>/StackB<T>。
解决方案
核心思路是让基类提供全局唯一的单例实例接口,子类复用该实例操作共享状态,子类自身的独立状态用静态成员维护。修改后的代码如下:
#include <iostream> int main(); class SingletonBase{ protected: int i=0; SingletonBase(int){} friend int main(); // 提供获取唯一基类实例的接口 static SingletonBase& get_instance() { static SingletonBase s(2); // 魔法静态单例 return s; } static void show(){ auto& s = get_instance(); s.i++; std::cout << "SingletonBase::i=" << s.i << "\n"; } }; class Singleton: public SingletonBase{ private: static int j; // 子类独立状态用静态成员维护 Singleton(int): SingletonBase(int{}){} // 保留构造函数不影响友元权限 public: static void show(){ auto& base_instance = get_instance(); // 复用基类的唯一实例 base_instance.i++; j++; std::cout << "Singleton::SingletonBase::i=" << base_instance.i << ". Singleton::j=" << j << "\n"; } }; // 初始化子类静态成员 int Singleton::j = 0; int main() { Singleton::show(); Singleton::show(); Singleton::show(); Singleton::show(); SingletonBase::show(); SingletonBase::show(); SingletonBase::show(); Singleton::show(); Singleton::show(); Singleton::show(); Singleton::show(); }
修改后输出
Singleton::SingletonBase::i=1. Singleton::j=1 Singleton::SingletonBase::i=2. Singleton::j=2 Singleton::SingletonBase::i=3. Singleton::j=3 Singleton::SingletonBase::i=4. Singleton::j=4 SingletonBase::i=5 SingletonBase::i=6 SingletonBase::i=7 Singleton::SingletonBase::i=8. Singleton::j=5 Singleton::SingletonBase::i=9. Singleton::j=6 Singleton::SingletonBase::i=10. Singleton::j=7 Singleton::SingletonBase::i=11. Singleton::j=8
原理说明
- 基类单例复用:通过
get_instance()统一提供唯一的基类实例,所有操作i的代码都指向同一个对象,保证i的全局递增。 - 子类状态独立:子类的
j用静态成员变量,确保子类自身的状态是唯一且持久的,不会随实例创建重复初始化。 - 友元权限保留:原有的
main友元权限不受影响,满足场景中ElementBase<T>访问StackBase<T>的需求。 - 模板类适配:对于实际场景中的模板类,该方案同样适用——模板实例化时,每个
StackA<T>/StackB<T>会生成独立的静态j,而StackBase<T>的get_instance()会为每个T生成唯一的基类单例,完美匹配需求。
内容的提问来源于stack exchange,提问作者GRamon
相关产品推荐
相关产品推荐

