友元函数无法构造 class 的唯一指针
Friend function is unable to construct a unique pointer of the class
我有一个特定的设计策略,我的 class 的构造函数是私有的,只能由 class 的朋友构造。在 friend 函数中,我正在尝试使用 std::make_unique
创建我的 class 的 unique_pointer,但它无法编译。我的 VC12 编译器抱怨
c:\program files (x86)\microsoft visual studio
12.0\vc\include\memory(1639): error C2248: 'Spam::Spam' : cannot access private member declared in class '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));
在您的示例中,Foo()
是一个 friend
,但它不是创建 Spam
的函数 - make_unique
在内部调用 new Spam
本身。简单的解决方法是让 Foo()
直接直接构造 Spam
:
void Foo() {
std::unique_ptr<Spam> spam(new Spam(10));
}
这是我见过的另一种方法,显然被称为 密码惯用法 :让 public 构造函数需要私有访问令牌。
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);
...
}
我有一个特定的设计策略,我的 class 的构造函数是私有的,只能由 class 的朋友构造。在 friend 函数中,我正在尝试使用 std::make_unique
创建我的 class 的 unique_pointer,但它无法编译。我的 VC12 编译器抱怨
c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1639): error C2248: 'Spam::Spam' : cannot access private member declared in class '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));
在您的示例中,Foo()
是一个 friend
,但它不是创建 Spam
的函数 - make_unique
在内部调用 new Spam
本身。简单的解决方法是让 Foo()
直接直接构造 Spam
:
void Foo() {
std::unique_ptr<Spam> spam(new Spam(10));
}
这是我见过的另一种方法,显然被称为 密码惯用法 :让 public 构造函数需要私有访问令牌。
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);
...
}