Ami*_*rsh 4 c++ constructor c++11
试图允许make_unique
使用私有 ctor 的类时,我发现两种情况之间存在以下奇怪的区别:
class A {
int _i;
A(): _i(7) {}
public:
template<typename... T>
static std::unique_ptr<A> create(T&&... t) {
struct enablePrivateCtor : public A {
using A::A;
};
return std::make_unique<enablePrivateCtor>(std::forward<T>(t)...);
}
void doIt() const {
std::cout << _i << std::endl;
}
};
int main() {
auto a = A::create();
a->doIt();
}
Run Code Online (Sandbox Code Playgroud)
输出:
7
Run Code Online (Sandbox Code Playgroud)
class A {
int _i;
A(int i): _i(i) {} // <- change 1, ctor getting int
public:
// no change here!
template<typename... T>
static std::unique_ptr<A> create(T&&... t) {
struct enablePrivateCtor : public A {
using A::A;
};
return std::make_unique<enablePrivateCtor>(std::forward<T>(t)...);
}
void doIt() const {
std::cout << _i << std::endl;
}
};
int main() {
auto a = A::create(7); // <- change 2, sending 7
a->doIt();
}
Run Code Online (Sandbox Code Playgroud)
编译错误:
unique_ptr.h: error: calling a private constructor of class 'enablePrivateCtor'
Run Code Online (Sandbox Code Playgroud)
为什么第一个 - 带有空 ctor - 可以,而第二个 - 非空 ctor - 不是?
默认构造函数永远不会被继承。因此,第一个enablePrivateCtor
生成默认构造函数,它调用基类默认构造函数。
当您继承构造函数时(如第二种情况),新构造函数与继承的构造函数具有相同的访问级别。既然A::A(int)
是私有的,那么也将是私有的enablePrivateCtor::enablePrivateCtor(int)
。所以你将无法用它构建。
如果您需要一个私有构造函数能够被间接调用(通过make_unique
/ emplace
/etc),那么您需要使用一个私有密钥类型。像这样:
class A;
class A_key
{
A_key() = default;
A_key(int) {} //Prevent `A_key` from being an aggregate.
friend class A;
};
class A {
int _i;
public:
A(int i, A_key): _i(i) {}
// no change here!
template<typename... T>
static std::unique_ptr<A> create(T&&... t)
{
return std::make_unique<A>(std::forward<T>(t)..., A_key{});
}
void doIt() const {
std::cout << _i << std::endl;
}
};
...
auto ptr = A::create(7);
A a(7, A_key{}); //Does not compile, since you're not a friend.
Run Code Online (Sandbox Code Playgroud)
A_key
可公开复制,但不可公开默认构造。所以非私有代码可以传递它们,但非私有代码不能创建它们。