2

C++ をできるだけ理解したい。基底クラスBと派生クラスがある場合DD d;派生オブジェクトをインスタンス化します。

  1. B & rb = d;rb派生オブジェクト を参照しますd。これは、基本クラスの新しいオブジェクトをインスタンス化しません。では、どのメモリ部分がrb参照されているのでしょうか?

  2. B newb = d;、これは基本クラスのコピーコンストラクターを呼び出します。オブジェクトdは最初にパラメーター type にバインドされ、const B&次に基本クラスの新しいオブジェクトがインスタンス化されます。

  3. B newbb(static_cast<B>(d));、このステートメントで何が達成されますか?

上記の 3 つのステートメントはcopy/move/conversion、オブジェクトの を理解するための私自身の方法です。しかし、彼らは本当に私を混乱させます。C++11 standardの対応する部分を読みましたが、コードを解釈する効果的で明確な方法を見つけることができません。

コードの引用で3つのステートメントを説明する答えを願っています。オブジェクトのコピー/移動/変換中に何が起こったか。


ヘルプ!皆さんからの回答を願っています!!

4

1 に答える 1

0

一般に、これらはすべてコピー操作である必要があり、場合によっては変換が最初に行われます。以下で移動操作について説明します。

パート 1: これから使用する言語は、標準とは少し異なる場合がありますが、rbオブジェクト全体を参照していると考える傾向がありますd。私がそう言う理由は、私がこのようなことをしているとき、Dほとんどの場合、少なくとも 1 つの仮想関数があり、 を介して呼び出された仮想関数は、 ではなくrbからバージョンを実行するからです。たとえば、次の場合:DB

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 にします。これは便利に聞こえるかもしれませんが、実際には、 の部分的なコピーではなく完全なコピーを作成するか、コピーをまったく作成せずに へのポインターまたは参照を使用することをお勧めします。BDBnewbdd

完全なコピーを作成したい場合は、次のように、おそらく仮想関数でコピーを実行する必要があります。

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 つのコンストラクターのどちらが呼び出されても発生します。

于 2013-06-29T06:51:14.353 に答える