短い答え:あなたの派生クラスのD 'は、デフォルトのバージョンは(コンパイラによって生成された新しいメンバ変数をすべき含まれていない場合は
:はいあなたはD
長い答えで作業を繰り返す必要がありますうまく動作します)。デフォルトのコピーコンストラクタは親コピーコンストラクタを呼び出し、デフォルトの代入演算子は親代入演算子を呼び出します。
しかし、クラス 'D'にリソースが含まれている場合は、いくつかの作業を行う必要があります。
私はあなたのコピーコンストラクタは少し奇妙見つける:彼らはベースアップからコピー構築されるように
B(const B& b){(*this) = b;}
D(const D& d){(*this) = d;}
は、通常、コンストラクタチェーンをコピーします。ここでは、代入演算子を呼び出すので、コピーコンストラクタはデフォルトのコンストラクタを呼び出して、オブジェクトをボトムアップから初期化する必要があります。次に、代入演算子を使用して再び下に移動します。これはむしろ非効率なようです。
割り当てを行うと、下から上(上から下へ)のコピーが行われますが、それを実行して強力な例外保証を提供することは難しいようです。ある時点でリソースがコピーに失敗し、例外をスローすると、オブジェクトは不確定な状態になります(これは悪いことです)。
通常、私はそれが他の方法で行われているのを見ました。
代入演算子は、コピーコンストラクタとスワップの観点から定義されています。これは、強力な例外保証を提供しやすくするためです。私はあなたがこのようにすることで強い保証を提供できるとは思わない(私は間違っている可能性がある)。
class X
{
// If your class has no resources then use the default version.
// Dynamically allocated memory is a resource.
// If any members have a constructor that throws then you will need to
// write your owen version of these to make it exception safe.
X(X const& copy)
// Do most of the work here in the initializer list
{ /* Do some Work Here */}
X& operator=(X const& copy)
{
X tmp(copy); // All resource all allocation happens here.
// If this fails the copy will throw an exception
// and 'this' object is unaffected by the exception.
swap(tmp);
return *this;
}
// swap is usually trivial to implement
// and you should easily be able to provide the no-throw guarantee.
void swap(X& s) throws()
{
/* Swap all members */
}
};
XからクラスDを派生させても、このパターンには影響しません。
確かに、基本クラスへの明示的な呼び出しを行うことによって少しの作業を繰り返す必要がありますが、これは比較的簡単です。
class D: public X
{
// Note:
// If D contains no members and only a new version of foo()
// Then the default version of these will work fine.
D(D const& copy)
:X(copy) // Chain X's copy constructor
// Do most of D's work here in the initializer list
{ /* More here */}
D& operator=(D const& copy)
{
D tmp(copy); // All resource all allocation happens here.
// If this fails the copy will throw an exception
// and 'this' object is unaffected by the exception.
swap(tmp);
return *this;
}
// swap is usually trivial to implement
// and you should easily be able to provide the no-throw guarantee.
void swap(D& s) throws()
{
X::swap(s); // swap the base class members
/* Swap all D members */
}
};
'foo'メソッドをオーバーライドしたいのであれば、' B :: operator =; 'を使って代入演算子を継承することができますが、コピーと移動のコンストラクタは継承できません:https://stackoverflow.com/q/49045026/5447906 –