静态函数无法访问 C++ 单例私有构造函数

C++ Singleton private constructor not accessible from static function

我在这里有一个单例 class 声明:

#ifndef GLFW_CONTEXT_H
#define GLFW_CONTEXT_H

#include <memory>

class GLFWContextSingleton
{
public:
    static std::shared_ptr<GLFWContextSingleton> GetInstance();
    ~GLFWContextSingleton();
    GLFWContextSingleton(const GLFWContextSingleton& other) = delete;
    GLFWContextSingleton* operator=(const GLFWContextSingleton* other) = delete;
    
private:
    GLFWContextSingleton();
};

#endif

以及此处显示的 GetInstance 函数的实现

std::shared_ptr<GLFWContextSingleton> GLFWContextSingleton::GetInstance()
{
    static std::weak_ptr<GLFWContextSingleton> weak_singleton_instance;
    auto singleton_instance = weak_singleton_instance.lock();

    if (singleton_instance == nullptr)
    {
        singleton_instance = std::make_shared<GLFWContextSingleton>();
        weak_singleton_instance = singleton_instance;
    }

    return singleton_instance;
}

但是调用 std::make_shared<GLFWContextSingleton>() 给我一个错误提示

‘GLFWContextSingleton::GLFWContextSingleton()’ is private within this context

我认为这个静态方法可以访问私有成员函数。是什么原因造成的,我该如何解决?

静态函数确实可以访问私有成员。 make_shared 没有。

make_shared是一个模板函数,它转发它得到的参数并调用指定class的构造函数。所以对默认构造函数的调用发生在 make_shared 函数内部,而不是在 GetInstance 函数内部,因此出现错误。

处理此问题的一种方法是使用私有嵌套 class 作为构造函数的唯一参数。

#include <memory>

class GLFWContextSingleton
{
private:
    struct PrivateTag {};
public:
    static std::shared_ptr<GLFWContextSingleton> GetInstance();
    ~GLFWContextSingleton();
    GLFWContextSingleton(const GLFWContextSingleton& other) = delete;
    GLFWContextSingleton* operator=(const GLFWContextSingleton* other) = delete;
    
    GLFWContextSingleton(PrivateTag);
};

std::shared_ptr<GLFWContextSingleton> GLFWContextSingleton::GetInstance()
{
    static std::weak_ptr<GLFWContextSingleton> weak_singleton_instance;
    auto singleton_instance = weak_singleton_instance.lock();

    if (singleton_instance == nullptr)
    {
        singleton_instance = std::make_shared<GLFWContextSingleton>(PrivateTag{});
        weak_singleton_instance = singleton_instance;
    }

    return singleton_instance;
}

int main() {

}

这样我们保留构造函数 public,但为了使用它,我们需要一个 PrivateTag,只有 class.

的成员可以访问