Все,
Я использую C ++ 14 и делаю более или менее стандартный синглтон. Я использую последнюю версию Visual Studio 2017. Этот код работает:
#include <memory>
class A
{
public:
static A& getInstance()
{
if (instance == nullptr)
instance = std::unique_ptr<A>(new A());
return *instance;
}
private:
A() {}
static std::unique_ptr<A> instance;
};
std::unique_ptr<A> A::instance = nullptr;
Однако, когда я изменяю создание экземпляра синглтона на это:
instance = std::make_unique<A>();
Я получаю ошибку компиляции, когда пытаюсь получить доступ к приватному члену:
Error C2248 'A::A': cannot access private member declared in class 'A'
c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.14.26428\include\memory 2510
Это похоже на ошибку для меня, так как две формы должны быть идентичны по функции? Мысли?
Цель std::unique_ptr<>
это контролировать время жизни объекта, на который указывает. Вы можете передать std::unique_ptr<>
вокруг, но это также передаст право собственности на указанный объект. Эта концепция не очень хорошо соответствует концепции синглтона. Существует только одно место, где разрешено создавать (или удалять) синглтон. Вам не нужно std::unique_ptr<>
для этого. Как уже говорилось в комментариях, для этого есть более простые способы. Я бы предпочел предложение @ Преториана:
static A& getInstance()
{
static A instance;
return instance;
}
Причина, по которой вы не можете использовать std::make_unique<>()
чтобы создать экземпляр вашего класса, конструктор является закрытым. Чтобы получить к нему доступ, вам нужна функция доступа, чтобы быть friend
, Посмотри на Как сделать std :: make_unique другом моего класса для этого. Другое решение состоит в том, чтобы предоставить открытый конструктор, требующий частного типа в качестве аргумента, как описано в int это решение.
instance = std::make_unique<A>();
это создает A
в функции make_unique
, Но тот номер, который вы хотите вызвать, является частным.
private:
struct ctor_permission_t{
explicit ctor_permission_t(int){};
};
public:
explicit A(ctor_permission_t):A(){}
};
затем
instance = std::make_unique<A>(ctor_permission_t{0});
ctor_permission_t
действует как знак, дающий своему владельцу право создавать A
, Мы передаем это make_unique
,
explicit int
ктор в ctor_permission_t
делает невозможным его создание без указания типа и только в пределах экземпляров и друзей A
могу назвать это, потому что это личное. Это затрудняет обход этого токена разрешения.