我这里有一个单例类声明:
\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\nRun Code Online (Sandbox Code Playgroud)\nGetInstance以及此处所示函数的实现
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}\nRun Code Online (Sandbox Code Playgroud)\n然而,调用std::make_shared<GLFWContextSingleton>()给我一个错误说
\xe2\x80\x98GLFWContextSingleton::GLFWContextSingleton()\xe2\x80\x99 is private within this context\nRun Code Online (Sandbox Code Playgroud)\n我认为这个静态方法可以访问私有成员函数。造成这种情况的原因是什么以及如何解决?
\n静态函数确实可以访问私有成员。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,我们需要一个只能由类成员访问的构造函数。