我对 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; ...
};
但是,作为work1
一个work_like
类,转发构造函数突然有了更好的匹配,因为复制/移动构造函数common_work
需要static_cast
从派生到基。
笔记 :
- Scott Meyers给出了类似的示例,其中复制构造触发转发构造函数,因为复制构造函数需要 const 添加,而转发构造函数不需要。但我认为,这个问题是由于错误的类设计引起的,而这里的问题是由于在隐式复制/移动期间传递给基类的参数不完全匹配。
- 我不能编写通用转发构造函数/赋值,并删除隐式的,因为删除的函数也参与重载决议,如果完全匹配会导致错误。
- 目前我的解决方案是制作
common_work
为 CRTP ,即作为模板参数传递的派生类类型,并在转发构造函数中将其过滤为enable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >
. 否则,我必须手动为基类手动编写复制/移动构造函数/赋值work1
,static_cast
这是错误的、容易出错的和维护风险。