[英]Inheriting constructors vs forwarding
C ++ 11允许继承构造函数,从而可以避免大量的样板,尤其是类似于包装类的东西。 但是,似乎您已经可以使用可变参数模板实现此功能。
class B
{
public:
B(int){//do something}
B(int, char){//do something}
};
使用继承构造函数:
class D : public B
{
public:
using B::B;
};
使用可变参数模板并转发:
class D : public B
{
public:
template <typename...Args>
D(Args&&... args) : B(std::forward<Args>(args)...)
{
}
};
虽然一致性(对待构造函数和方法的相同方式using
)和易用性很好的理由把继承构造成的语言,还有没有其他原因的第一个解决方案应首选第二? 我发现讨论继承构造函数的CWG文档( N1890和N1898 )只是注意以下内容并继续:
仅仅是一个历史事故阻止使用它来为构造函数和普通成员函数工作。 如果构造函数被称为“ctor”或“构造函数”而不是被其类的名称引用,那么这将起作用。 我们建议将其作为继承构造函数的机制。
最重要的原因是完美转发并不完美。 简单案例:
struct B {
B(int* ) { .. }
};
现在考虑:
D d{0};
如果我们继承构造函数,这很好。 如果我们完美转发,我们将尝试构造B(int )
,因为0
推导为int
,这是一个不存在的构造函数。 失败!
其他故障情况包括支撑初始化,仅声明的静态const数据成员,重载函数和位域。
完美转发并不完美。 特别是,0作为实际参数减少为int
而不是表示一般的nullvalue。 因此,对于构造函数采用指针参数, 0
将作为继承构造函数的实际参数,但不用于转发。
我认为我曾经提到的另一个原因是,问题(我们真的需要继承构造函数)是否被播出,继承构造函数是一个简单的符号,用于概念上简单的事情,用于简单类的上下文中。 在C ++中有足够的强制复杂性和强制样板。
维护问题(编译器错误)可能会导致'使用'的偏好:
struct Base
{
Base(int) {}
};
struct Derived : public Base
{
using Base::Base;
};
struct DerivedTemplate : Base
{
template <typename...Args>
DerivedTemplate(Args&&... args)
: Base(std::forward<Args>(args)...)
{}
};
int main()
{
// error: no matching function for call to ‘Derived::Derived(int, int)’
Derived d(1, 2);
// In instantiation of ‘DerivedTemplate::DerivedTemplate(Args&& ...) [with Args = {int, int}]’:
// required from here
// error: no matching function for call to ‘Base::Base(int, int)’
DerivedTemplate dt(1, 2);
}
此外,每个模板实例化都是一个不同的构造函数(使用时不会相乘)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.