1

次のコード:

#include <stdio.h>
class Parent
{
public:
    virtual void func() {printf("Parent\n");}
};

class Child1 : public Parent
{
    virtual void func() {printf("Child1\n");}
};

class Child2 : public Parent
{
    virtual void func() {printf("Child2\n");}
};

int main(int argc, char* argv[])
{
    Parent & obj = Child1();
    obj.func();
    obj = Child2();
    obj.func();
    return 0;
}

次の結果が得られます。

expected: Child1 Child2.

actual: Child1 Child1. 

(VS2010でコンパイル)

vptrは割り当てによって変更されないと思います。それを再作成させる方法はありますか(Parentへのポインターを使用してnewを使用して割り当てる以外)?

ありがとう

4

5 に答える 5

3

Child2 型の引数を使用して、まだ Child1 型である obj の既定の代入演算子を呼び出しています。オブジェクト自体はまだタイプChild1です。operator =これを確認するには、3 つのクラスすべてに実装し、そこに print ステートメントを挿入します。

于 2011-11-22T10:26:20.853 に答える
1

参照を再配置することはできません。それらは、存続期間全体にわたって同じオブジェクトを参照します。参照するオブジェクトを変更できるものが必要な場合は、参照の代わりに [スマート] ポインターを使用する必要があります。

ここで行っているのは、 のインスタンスを のインスタンスに割り当てることによって、 のインスタンスをスライスすることです。Child2Child1

于 2011-11-22T10:29:50.520 に答える
1
Parent & obj = Child1();

型のオブジェクトへの参照を作成しますChild1。これは言ってるような

Child1 c1;
Parent& obj = c1;

objc1は、 タイプ のオブジェクトであるの別の名前になりましたChild1

obj = Child2();
obj.func();

さて、これは言っているようなものです

c1 = Child2();
c1.func();

funcご覧のとおり、まだtype のオブジェクトを呼び出していますChild1

于 2011-11-22T10:30:09.197 に答える
1

C++ の 2 つの基本的なプロパティ: オブジェクトは、一度作成されると、その型を変更することはありません。参照は、一度初期化されると、常に同じオブジェクトを参照します。

ここで起こっていることは、提供された非仮想operator=forコンパイラを呼び出しているというParentことです。これは、ほぼ確実に望んでいたことではありません。ただし、より一般的には、割り当てと継承はうまく連携しません (正確には、オブジェクトの型を変更できないためです)。boost::noncopyableほとんどの場合、継承を使用する場合は、代入を禁止する必要があります (たとえば、から継承することにより)。レター/エンベロープのイディオムを使用して、ポリモーフィック クラスの値セマンティクスを実装することは可能ですが、それは重い解決策であり、ほとんど適切ではありません。

(あなたのコードは C++ コンパイラでコンパイルされないことを付け加えるかもしれません。非 const への参照を一時的に初期化していますが、これは正当な C++ ではありません。これを許可するのは Microsoft の拡張機能です。)

于 2011-11-22T10:34:14.390 に答える
0

あなたがしていることは、コンパイルでエラーになるはずです。Child2()一時変数 ( で作成) を参照変数に割り当てることはできません。の前にインスタンスを作成し、Child2その変数を敬虔に割り当てる必要があります。

于 2011-11-22T10:30:23.257 に答える