You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++单例静态函数调用std::make_shared无法访问私有构造函数问题

错误原因

你遇到的编译报错本质是权限访问上下文的问题:
类的静态成员函数确实有权限调用私有构造函数,但std::make_shared<T>是标准库提供的全局模板函数,构造对象的实际操作是在std::make_shared的内部逻辑中执行的,该函数不属于GLFWContextSingleton的成员也没有被声明为友元,因此没有权限访问类的私有构造函数,和你在哪个函数里调用std::make_shared无关。

修复方案

不推荐声明std::make_shared为友元的方式,该方式强依赖标准库的内部实现,可移植性差,常用的可行修复方案有两种:

  • 方案1:直接用new构造对象(改动最小)
    放弃使用std::make_shared,直接在GetInstance函数内调用new创建对象,此时构造函数的调用上下文是类的静态成员函数,有权限访问私有构造,修改后的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::shared_ptr<GLFWContextSingleton>(new GLFWContextSingleton());
        weak_singleton_instance = singleton_instance;
    }

    return singleton_instance;
}
  • 方案2:密钥模式保留std::make_shared的优化特性
    std::make_shared会把对象和控制块分配在同一块内存,性能更优,如果要保留这个特性,可以用密钥访问的方式实现:
    首先修改类的声明,增加私有密钥类型,修改构造函数的公开签名:
#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;

    // 构造函数公开,但需要传入私有类型的密钥,外部无法调用
    GLFWContextSingleton(struct ConstructorToken) {}
    
private:
    // 私有密钥类型,只有类内部可以访问
    struct ConstructorToken {};
};

#endif

然后修改GetInstance的实现,传入密钥调用std::make_shared:

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)
    {
        // 类内部可以访问ConstructorToken类型,构造合法
        singleton_instance = std::make_shared<GLFWContextSingleton>(ConstructorToken{});
        weak_singleton_instance = singleton_instance;
    }

    return singleton_instance;
}

内容的提问来源于stack exchange,提问作者nick2225

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 03:54:04