【发布时间】:2017-09-11 14:11:19
【问题描述】:
试图在具有私有 ctor 的类上允许 make_unique 我在两种情况下遇到了以下奇怪的区别:
案例 1 - 空 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();
}
输出:
7
案例 2 - 非空 ctor - 无法编译
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();
}
编译错误:
unique_ptr.h: error: calling a private constructor of class 'enablePrivateCtor'
为什么第一个 - 带有空 ctor - 可以,而第二个 - 非空 ctor - 不行?
【问题讨论】:
-
与您的问题无关,以及更多帮助您改进问题的提示:我们不需要看到
A类两次。相反,您可以只使用第一个示例,但是使用像auto b = A::create(7); // Does not compile这样的第二行可以不必显示程序正在运行或其输出,因为问题是关于构建错误(我假设)。 -
仅供参考:这个想法是错误的。你不能像这样使用派生类;您的
create函数调用 UB。相反,您应该依赖一个私有的“密钥”类实例,它只能由有权访问A的人构建。您想要“私有”的 A 的构造函数应该将该类的实例作为参数。这样,那些有权访问A的人就可以创建这样一个实例并将其传入。 -
@Someprogrammerdude:这些例子是不同的。在第二个示例中,
A将参数传递给其私有构造函数。 -
默认的 c'tor 并不是真正继承的。它是由编译器自动生成的。
-
@MooingDuck:
enablePrivateCtor派生自A,但A没有虚拟析构函数。所以从基类指针中销毁它(当你将它转换为unique_ptr<A>时会发生这种情况将产生UB。
标签: c++ c++11 constructor