我对C++隐式复制构造函数的理解类似于
T(T const& x) :
base1(x), base2(x) ... ,
var1(x.var1), var2(x.var2)...
{}
移动构造函数、复制和移动赋值运算符也遵循类似的模式。
为什么它没有定义类似于以下内容?
T(T const& x) :
base1(static_cast<base1 const&>(x)),
base2(static_cast<base2 const&>(x)) ... ,
var1(x.var1), var2(x.var2)...
{}
例子
我有一个类,它具有隐式拷贝/移动构造函数/赋值运算符,以及一些转换构造函数。我正在将工作委托给某个实现类。
class common_work //common implementation of many work like classes
{
common_work(common_work const&) = default;
common_work(common_work&&) = default;// ... implicit constructors work for me.
//a forwarding constructor which can take many work like objects
template<class T, enable_if<work_like<T> > >
common_work(T&& x) { ... }
};
class work1 //one of the implementation
{
work1(work1 const& ) = default;
work1(work1&& ) = default; ...
common_work impl_;
};
这很好,因为work1
的复制/移动构造函数调用了common_work
的复制/移动构造函数,并且其他构造函数(未在代码中显示)使用了转发构造函数,该构造函数将从另一种work
类型进行转换。
然后我想让work1
从common_work
继承,出于EBO和其他原因。所以新的work1
类看起来像:
class work1 : private common_work
{
work1(work1 const& ) = default;
work1(work1&& ) = default; ...
};
作为一个work_like
类,work1
在使用转发构造函数时得到了更好的匹配,因为common_work
的复制/移动构造函数需要从派生类向基类进行static_cast
。
注意:
- Scott Meyers提供了一个类似的例子,其中复制构造函数触发转发构造函数,因为复制构造函数需要常量添加,而转发构造函数不需要。但我认为,这个问题是由错误的类设计引起的,而这里的问题是在隐式复制/移动期间传递给基类的参数不是精确匹配。
- 我不能编写通用的转发构造函数 / 赋值,并删除隐式函数,因为删除的函数也参与重载决议,如果匹配恰好,则会导致错误。
- 目前我拥有的解决方案是使
common_work
成为 CRTP ,即派生类类型作为模板参数传递,并在转发构造函数中将其过滤为enable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >
。否则,我必须手动编写work1
的复制/移动构造函数/赋值,并明确地将其转换为基类,这很容易出错,存在维护危险。
is_same<T,Derived>
,而应该是is_same<remove_ref<T>,Derived>
。 - abir