继承构造函数与转发
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
,而不是表示一般的 null 值。因此,当构造函数采用指针参数时,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);
}
此外,每个模板实例化都是一个不同的构造函数(而使用不会乘法)
相关文章:
- 在按值调用 (c++) 中转发构造函数参数
- 完美的转发和构造函数
- 我可以在构造函数的主体中转发构造吗?
- 通过类型别名从构造函数转发模板推导
- 如何通过可变参数模板将多个构造函数参数转发到数组初始值设定项列表?
- 完美的转发构造函数和已删除的构造函数
- 如何构造一个 std::variant 类型对象,其自身 Templated 和构造函数转发参数
- 使用完美转发的模板转换构造函数
- 禁用 std::optional的转发构造函数
- 通过转发构造函数参数来构建基于可变参数模板的 mixin
- 为什么我们应该为initializer_list的情况过多载荷转发构造函数
- 在类层次结构中,完美的转发构造函数和复制构造函数之间的冲突
- 完美的转发功能与完美的转发构造函数
- 转发构造函数调用基类的复制构造函数2次
- 使用declard和参数转发构造函数隐式复制结构
- 临时寿命和完美的转发构造函数
- 如何为类似元组的可变类创建一个完美的转发构造函数
- 复制构造函数和转发构造函数之间存在冲突
- 单例、奇怪的重复模板模式和转发构造函数参数
- 通过接口转发构造函数参数