我有一个特定的设计策略,我的类的构造函数是私有的,只能由类的朋友构建。在友元函数内部,我正在尝试使用std::make_unique
but创建我的类的unique_pointer,它不能编译。我的VC12编译器抱怨
c:\ program files(x86)\ microsoft visual studio 12.0 \ vc \ include \ memory(1639):错误C2248:'Spam :: Spam':无法访问类'Spam'中声明的私有成员
编译过程中失败的相关代码如下
#include <memory>
class Spam {
public:
friend void Foo();
private:
Spam(int mem) :mem(mem) {}
int mem;
};
void Foo() {
std::unique_ptr<Spam> spam = std::make_unique<Spam>(10);
}
为什么我无法编译?
在你的情况下,函数make_unique
试图创建一个Spam
的实例,该函数不是朋友。从朋友函数内部调用非朋友函数不会使非朋友函数充满朋友状态。
要解决这个问题,你可以写Foo
:
std::unique_ptr<Spam> spam(new Spam(10));
这是我见过的另一种方法,显然称为密码习语:公共构造函数需要私有访问令牌。
class Spam {
struct Token {};
friend void Foo();
public:
Spam(Token, int mem) : mem(mem) {}
private:
int mem;
};
void Foo() {
std::unique_ptr<Spam> spam = std::make_unique<Spam>(Spam::Token{}, 10);
}
void Bar() {
// error: 'Spam::Token Spam::token' is private
// std::unique_ptr<Spam> spam = std::make_unique<Spam>(Spam::Token{}, 10);
}
Why am I not able to compile?
你无法编译,因为make_unique
不是Spam
的朋友。
使make_unique
成为朋友的另一种解决方案是将unique_ptr的创建移动到Spam
。
class Spam {
...
private:
Spam(int) {}
static unique_ptr<Spam> create( int i )
{ return std::unique_ptr<Spam>( new Spam(i) ); }
};
然后让Foo
称之为。
void Foo() {
std::unique_ptr<Spam> spam = Spam::create(10);
...
}
在你的例子中,Foo()
是一个friend
,但它不是创建Spam
的函数 - make_unique
在内部调用new Spam
本身。简单的解决方法就是让Foo()
直接构建Spam
:
void Foo() {
std::unique_ptr<Spam> spam(new Spam(10));
}