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
その後、EBO などのcommon_work
理由でを継承しようと考えました。新しい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
明示的に手動で作成する必要があり、バグが発生しやすく、エラーが発生しやすく、メンテナンスが危険です。