C++ Singleton 私有构造函数无法从静态函数访问

nic*_*225 3 c++ singleton

我这里有一个单例类声明:

\n
#ifndef GLFW_CONTEXT_H\n#define GLFW_CONTEXT_H\n\n#include <memory>\n\nclass GLFWContextSingleton\n{\npublic:\n    static std::shared_ptr<GLFWContextSingleton> GetInstance();\n    ~GLFWContextSingleton();\n    GLFWContextSingleton(const GLFWContextSingleton& other) = delete;\n    GLFWContextSingleton* operator=(const GLFWContextSingleton* other) = delete;\n    \nprivate:\n    GLFWContextSingleton();\n};\n\n#endif\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
std::shared_ptr<GLFWContextSingleton> GLFWContextSingleton::GetInstance()\n{\n    static std::weak_ptr<GLFWContextSingleton> weak_singleton_instance;\n    auto singleton_instance = weak_singleton_instance.lock();\n\n    if (singleton_instance == nullptr)\n    {\n        singleton_instance = std::make_shared<GLFWContextSingleton>();\n        weak_singleton_instance = singleton_instance;\n    }\n\n    return singleton_instance;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然而,调用std::make_shared<GLFWContextSingleton>()给我一个错误说

\n
\xe2\x80\x98GLFWContextSingleton::GLFWContextSingleton()\xe2\x80\x99 is private within this context\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

sup*_*per 6

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

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

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

#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() {

}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我们可以将构造函数保持为公共,但为了使用它PrivateTag,我们需要一个只能由类成员访问的构造函数。