You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何继承魔法静态单例并共享基类单例实例?

问题:魔法静态单例子类共享基类单例实例

原代码

#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

原理说明

  1. 基类单例复用:通过get_instance()统一提供唯一的基类实例,所有操作i的代码都指向同一个对象,保证i的全局递增。
  2. 子类状态独立:子类的j用静态成员变量,确保子类自身的状态是唯一且持久的,不会随实例创建重复初始化。
  3. 友元权限保留:原有的main友元权限不受影响,满足场景中ElementBase<T>访问StackBase<T>的需求。
  4. 模板类适配:对于实际场景中的模板类,该方案同样适用——模板实例化时,每个StackA<T>/StackB<T>会生成独立的静态j,而StackBase<T>的get_instance()会为每个T生成唯一的基类单例,完美匹配需求。

内容的提问来源于stack exchange,提问作者GRamon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:45:01