【问题标题】:C++ Singleton private constructor not accessible from static function静态函数无法访问 C++ Singleton 私有构造函数
【发布时间】:2021-10-20 20:38:50
【问题描述】:

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

#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&lt;GLFWContextSingleton&gt;() 的调用给了我一个错误提示

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

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

【问题讨论】:

  • 函数std::make_shared&lt;GLFWContextSingleton&gt;() 不是您班级的friend。它不能使用private 构造函数。
  • 是的,static 函数具有访问权限。你可以做singleton_instance.reset(new GLFWContextSingleton); - 这是你调用的函数make_shared,它没有访问权限。
  • 你有什么理由想要一个shared_ptr 给单身人士顺便说一句? Mayers 类型的单身人士不会工作吗?
  • @TedLyngmo 我认为使用shared_ptr 可能会更好,因为我可以使用weak_ptr 来测试对象是否已初始化。但既然你提到了它,我认为不需要它,并且可能只返回对裸静态对象本身的引用。
  • 更不用说,GetInstance() 的显示方式,如果多个线程同时调用GetInstance(),就会出现竞争条件。返回一个静态对象可以避免这种情况。

标签: c++ singleton


【解决方案1】:

静态函数确实可以访问私有成员。 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() {

}

这样我们保持构造函数是公开的,但是为了使用它,我们需要一个PrivateTag,只有类的成员可以访问。

【讨论】:

  • 谢谢!我完全忘记了该类的访问权限仅在静态函数的直接级别可用,并且不会传播到其他调用。
猜你喜欢
  • 1970-01-01
  • 2017-04-04
  • 2021-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 2017-04-07
  • 2018-12-12
相关资源
最近更新 更多