10.8.4 Implicit Copy-Assignment for Virtual Bases
When a base class is virtual, only one subobject of the base class belongs to each full object. Also, the constructors and destructors are invoked only once, and called from the most-derived class. However, such objects behave unspecified when being assigned. For example:
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; }
The C++ standard specifies that ` Base::Base ' is only called once when constructing or copy-constructing a Derived object. It is unspecified whether ` Base::operator= ' is called more than once when the implicit copy-assignment for Derived objects is invoked (as it is inside ` func ' in the example).
G++ implements the “intuitive” algorithm for copy-assignment: assign all direct bases, then assign all members. In that algorithm, the virtual base subobject can be encountered more than once. In the example, copying proceeds in the following order: `
val
', `
name
' (via strdup
), `
bval
', and `
name
' again.
If application code relies on copy-assignment, a user-defined copy-assignment operator removes any uncertainties. With such an operator, the application can define whether and how the virtual base subobject is assigned.