一般に、これらはすべてコピー操作である必要があり、場合によっては変換が最初に行われます。以下で移動操作について説明します。
パート 1: これから使用する言語は、標準とは少し異なる場合がありますが、rb
オブジェクト全体を参照していると考える傾向がありますd
。私がそう言う理由は、私がこのようなことをしているとき、D
ほとんどの場合、少なくとも 1 つの仮想関数があり、 を介して呼び出された仮想関数は、 ではなくrb
からバージョンを実行するからです。たとえば、次の場合:D
B
class B
{
public:
virtual int get_value() { return 10; }
};
class D: public B
{
public:
virtual int get_value() { return 20; }
};
次にrb.get_value()
、あなたが考えているような 10 ではなく、20 を返します。
パート 2: これは実際には、ほとんどやりたくないことです。ここで起こることは、「スライス」と呼ばれるプロセスによってd
が に変換されることです。これは、固有だった部分を破棄してその部分だけを残し、それをコピーして create にします。これは便利に聞こえるかもしれませんが、実際には、 の部分的なコピーではなく完全なコピーを作成するか、コピーをまったく作成せずに へのポインターまたは参照を使用することをお勧めします。B
D
B
newb
d
d
完全なコピーを作成したい場合は、次のように、おそらく仮想関数でコピーを実行する必要があります。
class B
{
public:
virtual B *clone()
{
return new B(*this);
}
};
class D: public B
{
public:
virtual B *clone()
{
return new D(*this);
}
};
パート 3: これは基本的にパート 2 と同じstatic_cast
です。繰り返しますが、これはおそらく頻繁にやりたいことではないでしょう。
コンテキストによっては、使用しているような式が代わりに移動操作になる場合があります。たとえば、d
破棄されようとしている場合、コンパイラはそれを認識し、コピーではなく移動関数を呼び出す可能性があります。これは、一般に移動の方が効率的であるためです。例えば:
B foo()
{
D d;
return d;
}
C++11 では、return-statement は、戻り値を作成するためにコピー コンストラクターではなく移動コンストラクター (存在する場合) を呼び出す場合があります。とはいえ、効果はかなり似ているはずです。パート 2 とパート 3 で発生するスライスは、2 つのコンストラクターのどちらが呼び出されても発生します。