[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.10.3 仮想基底に対する暗黙kのコピー代入

基底クラスが仮想クラスである場合、基底クラスのサブオブジェクト一つだけが それぞれの完全なオブジェクトに属する。 また、コンストラクタとデストラクタは一度だけ起動され、最下位の派生クラス から呼び出される。だが、このようなオブジェクトが代入されたときの 動作は規定されていない。例えば、

 
struct Base{
  char *name;
  Base(char *n) : name(strdup(n)){}
  Base& operator= (const Base& other){
   free (name);
   name = strdup (other.name);
  }
};

struct A:virtual Base{
  int val;
  A():Base("A"){}
};

struct B:virtual Base{
  int bval;
  B():Base("B"){}
};

struct Derived:public A, public B{
  Derived():Base("Derived"){}
};

void func(Derived &d1, Derived &d2)
{
  d1 = d2;
}

C++ の規格は、Derived のオブジェクトを構築するときやコピー構築するときは、 ‘Base::Base’ は一度しか呼び出されないことを規定している。 Derived のオブジェクトに対する暗黙のコピー代入が起動されたときに (上の例の ‘func’ の中のように)、‘Base::operator=’ が二回以上 呼ばれるかどうかは規定されていない。

g++ は、コピー代入について「直観的」なアルゴリズムを実装している。 これは全ての直接の基底を代入し、次に全てのメンバを代入するというものだる。 このアルゴリズムでは、仮想基底のサブオブジェクトに何度も出くわす。 上の例では、コピーは次の順序で進む。‘val’、‘name’(strdup 経由で)、‘bval’、再び ‘name’ となる。

アプリケーションコードをコピー代入を元にしたいのなら、 ユーザ定義のコピー代入演算子を定義すれば不確実さがなくなる。 そういう演算子を使えば、アプリケーションは、仮想基底サブオブジェクトが 代入されるかどうか、それに、その方法を定義することができる。


This document was generated using texi2html 1.78.