温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C++ 单例模式

发布时间:2020-10-25 14:00:13 来源:网络 阅读:804 作者:qdqade 栏目:编程语言
1.
//singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H

template <typename T>
class singleton
{
public:
    static T* get_instance();
private:
        // static instance 的作用,主要是为了让所有的 单例 都在main 执行前,
        //或者so加载成功时,调用其构造函数
    class creator
    {   
        public:
        creator()
        {   
            get_instance();
        }   
        inline void dono()const{}
    };  
    static creator instance;
};

//模板内嵌套类,需要用typename告知其是类型
template <typename T>
typename singleton<T>::creator singleton<T>::instance;
template <typename T>
T* singleton<T>::get_instance()
{
    static T t;
    instance.dono();
    return &t; 
}
#endif
#ifndef TESTC_H
#define TESTC_H
#include <iostream>
using namespace std;
class testc
{
public:
    ~testc(){cout<<"~test"<<endl;}
    testc()
    {   
        hasinit=false;
        cout<<"testc is called"<<endl;
    }   
    bool init(int mm) 
    {   
        if(hasinit)
            return true;
        m=mm;
        cout<<"init is called"<<endl;
        hasinit=true;
    }   
    bool hasinit;
    int m;
};

#endif
#include "singleton.h"
#include "testc.h"

int main()
{
    testc * cc=singleton<testc>::get_instance();
    cc->init(1);
    cout<<cc->m<<endl;
    testc *cc2=singleton<testc>::get_instance();
    cc2->init(2);
    cout<<cc2->m<<endl;
    testc *c3=new testc;
    c3->init(3);
    cout<<c3->m<<endl;
}
testc is called
init is called
1
1
testc is called
init is called
3
~test

2.跨so 单例模板 会产生多实例问题
问题初步原因:
不同so中会对 类模板进行实例化,并在不同so中各存在 一个类副本。网上有人确认过,singleton<A> 产生的类A代码,在不同so中 typeid(singleton<A>) 的返回值 type_info 不相等,但我自己确认结果是 两者相等。
解决方法:
想办法,让单例类的实例化 singleton<A> 只在一个so中进行;
class A
{
...
     A* get_instance(){return singleton<A>::get_instance();}
...
};
想获得单例时 执行 A::get_instance(),而非 singleton<A>::get_instance();

在这里:testc 类会被 两个不同的so liba.so,libb.so 使用其单例,如果按照1中的方法,则 在liba.so
和libb.so中都会 调用 singleton<testc>::get_instance(),但因为 liba.so ,libb.so 是不同的编译单元,
编译器会 为两个 so产生 两份类 testc 单例化的副本。(后续在好好梳理)

解决方法
#ifndef TESTC_H
#define TESTC_H
#include <iostream>
using namespace std;
class testc
{
public:
    ~testc(){cout<<"~test"<<endl;}
    testc()
    {   
        hasinit=false;
        cout<<"testc is called"<<endl;
    }
    
    testc *get_instance(){return singleotn<testc>::get_instance()}   
    bool init(int mm) 
    {   
        if(hasinit)
            return true;
        m=mm;
        cout<<"init is called"<<endl;
        hasinit=true;
    }   
    bool hasinit;
    int m;
};

#endif

tectc::get_instance()

参考文献,感谢两位博主,

http://blog.cnbang.net/tech/2229/

http://blog.csdn.net/crayondeng/article/details/24853471

http://blog.csdn.net/fullsail/article/details/8483106


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI