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