12

次の例ではどうなりますか?

struct B { };
struct D1 : B  { };
struct D2 : B  { };
int main()
{
    D1 d;
    D2 d2;
    B& x = d;
    x = d2;
}

参照が再割り当てされていないことはわかっています。xまだを参照してdいますが、どのように割り当てることができますd2d

もう少し:

struct B
{
    B () { x = 0; }
    int x;
    virtual void foo () { cout << "B" << endl; }
};
struct D1 : B
{
    D1 () { x = 1; }
    virtual void foo () { cout << "D1" << endl; }
};
struct D2 : B
{
    D2 () { x = 2; }
    virtual void foo () { cout << "D2" << endl; }
};

int main()
{
D1 d;
D2 d2;
B& x = d;
x.foo();   //D1
               //x.x is 1 here
x = d2;
x.foo();   //also D1
               //but x.x is 2 here
}

更新されたようですx.xが、vftableは更新されていません...なぜですか?

4

3 に答える 3

11

xB基本クラスサブオブジェクトを参照しdます。割り当ては、ベース サブオブジェクトをx = d2 スライスし、その値を のサブオブジェクトに割り当てます。Bd2d

これは通常、意図的に行われません。

編集:

xx は更新されたようですが、vftable は更新されていません...なぜですか?

それが代入演算子B::operator=です。C++ の基本クラスは、自分が基本クラスであることをまったく認識していません。また、オブジェクトの型は、その存続期間中に変更することはできません。最も近い代替手段は C++11 のstd::moveで、これは a 内の古いBオブジェクトをD1新しいD2オブジェクトに転送できます。その後、古いオブジェクトを破棄します。

于 2012-06-16T17:44:14.530 に答える
3

必要に応じて、自分で = を実装し、適切な具象型をチェックして (またはエラーを発生させて) スライスを「回避」できます。以下のエラーの例を参照してください。

struct B { 
  virtual B& operator = (B& b) = 0;
};
struct D1 : B  { 
  D1& operator = (B& b) {
    if ( dynamic_cast<D1*>(&b) == 0 ) {
      cerr << "Cannot assign non D1 to D1" << endl;
      exit(255);
    }
    // handle the assignments
    return *this;
  }
};
struct D2 : B  { 
  int c;
  D2& operator = (B& b) {
    if ( dynamic_cast<D2*>(&b) == 0 ) {
      cerr << "Cannot assign non D2 to D2" << endl;
      exit(255);
    }
    // handle the assignments
    return *this;
  }
};
于 2012-06-16T18:01:31.807 に答える
1

あなたの場合、この方法でメンバーを割り当てると、Base クラスに属さないメンバーがスライスされます。つまり、この場合、ある Base クラス オブジェクトを別のオブジェクトに割り当てているかのようにコピーされます。

于 2012-06-16T17:44:42.440 に答える