Private constructor and make_shared

后端 未结 3 1557
生来不讨喜
生来不讨喜 2021-01-06 20:34

I have a singleton class with a private constructor. In the static factory method I do the following:

shared_ptr MyClass::GetInstance()
{
             


        
3条回答
  •  有刺的猬
    2021-01-06 21:41

    1. As mentioned, std::make_shared or its component parts don't have access to private members.

    2. the call_once and once_flag are un-necessary. They are implicit in c++11 static initialisation,

    3. You normally would not want to expose the shared pointer.

     

    class MyClass
    {
        MyClass() {}
    
    public:
        static MyClass& GetInstance()
        {
            static auto instance = MyClass();
            return instance;
        }
    };
    

    However, there is one case I can imagine where you would want to expose a shared pointer to the impl - this is in the case where the class can choose to 'break off' or 'reset' the impl to a new one. In this case I would consider code like this:

    class MyClass2
    {
        MyClass2() {};
    
        static auto& InternalGetInstance()
        {
            static std::shared_ptr instance { new MyClass2 };
            return instance;
        }
    
    public:
    
        static std::shared_ptr GetInstance()
        {
            return std::atomic_load(std::addressof(InternalGetInstance()));
        }
    
        static void reset() {
            std::atomic_store(std::addressof(InternalGetInstance()),
                            std::shared_ptr(new MyClass2));
    
        }  
    };
    

    However, in the end, it is my view that 'staticness' of a class should be an implementation detail, and unimportant to the user of the class:

    #include 
    #include 
    
    class MyClass
    {
        // internal mechanics
    
        struct Impl {
    
            auto doSomething() {
                // actual implementation here.
            }
        };
    
        // getImpl now becomes the customisation point if you wish to change the
        // bahviour of the class later
        static Impl& getImpl() {
            static auto impl = Impl();
            return impl;
        }
    
    
        // use value semantics - it makes for more readable and loosely-coupled code
    public:
        MyClass() {}
    
        // public methods defer to internal implementation
    
        auto doSomething() {
            return getImpl().doSomething();
        }
    };
    
    
    int main() {
    
        // note: just create objects
        auto mc = MyClass();
        mc.doSomething();
    
        // now we can pass the singleton as an object. Other functions don't even
        // need to know it's a singlton:
    
        extern void somethingElse(MyClass mc);
        somethingElse(mc);
    }
    
    void somethingElse(MyClass mc)
    {
    
    }
    

提交回复
热议问题