______________________________________________________________________
10 Derived classes [class.derived]
______________________________________________________________________
1 A list of base classes can be specified in a class definition using
the notation:
base-clause:
: base-specifier-list
base-specifier-list:
base-specifier
base-specifier-list , base-specifier
base-specifier:
::opt nested-name-specifieropt class-name
virtual access-specifieropt ::opt nested-name-specifieropt class-name
access-specifier virtualopt ::opt nested-name-specifieropt class-name
access-specifier:
private
protected
public
The class-name in a base-specifier shall not be an incompletely
defined class (_class_); this class is called a direct base class for
the class being declared. During the look up for a base class name,
object, function, and enumerator names are ignored
(_basic.scope.hiding_). If the name found is not a class-name, the
program is ill-formed. A class B is a base class of a class D if it
is a direct base class of D or a direct base class of one of D's base
classes. A class is an indirect base class of another if it is a base
class but not a direct base class. A class is said to be (directly or
indirectly) derived from its (direct or indirect) base classes.
[Note: for the meaning of access-specifier see _class.access_. ]
Unless redefined in the derived class, members of a base class are
also considered to be members of the derived class. The base class
members are said to be inherited by the derived class. Inherited mem
bers can be referred to in expressions in the same manner as other
members of the derived class, unless their names are hidden or ambigu
ous (_class.member.lookup_). [Note: the scope resolution operator ::
(_expr.prim_) can be used to refer to a direct or indirect base member
explicitly. This allows access to a name that has been redefined in
the derived class. A derived class can itself serve as a base class
subject to access control; see _class.access.base_. A pointer to a
derived class can be implicitly converted to a pointer to an accessi
ble unambiguous base class (_conv.ptr_). An lvalue of a derived class
type can be bound to a reference to an accessible unambiguous base
class (_dcl.init.ref_). ]
2 The base-specifier-list specifies the type of the base class subob
jects contained in an object of the derived class type. [Example:
class Base {
public:
int a, b, c;
};
class Derived : public Base {
public:
int b;
};
class Derived2 : public Derived {
public:
int c;
};
Here, an object of class Derived2 will have a sub-object of class
Derived which in turn will have a sub-object of class Base. ]
3 The order in which the base class subobjects are allocated in the most
derived object (_intro.object_) is unspecified. [Note: a derived
class and its base class sub-objects can be represented by a directed
acyclic graph (DAG) where an arrow means "directly derived from." A
DAG of sub-objects is often referred to as a "sub-object lattice."
Base
|
|
Derived
|
Derived2
The arrows need not have a physical representation in memory. ]
4 [Note: initialization of objects representing base classes can be
specified in constructors; see _class.base.init_. ]
5 [Note: A base class subobject might have a layout (_basic.stc_) dif
ferent from the layout of a most derived object of the same type. A
base class subobject might have a polymorphic behavior (_class.cdtor_)
different from the polymorphic behavior of a most derived object of
the same type. A base class subobject may be of zero size (_class_);
however, two subobjects that have the same class type and that belong
to the same most derived object must not be allocated at the same
address (_expr.eq_). ]
10.1 Multiple base classes [class.mi]
1 A class can be derived from any number of base classes. [Note: the
use of more than one direct base class is often called multiple inher
itance. ] [Example:
class A { /* ... */ };
class B { /* ... */ };
class C { /* ... */ };
class D : public A, public B, public C { /* ... */ };
--end example]
2 [Note: the order of derivation is not significant except as specified
by the semantics of initialization by constructor (_class.base.init_),
cleanup (_class.dtor_), and storage layout (_class.mem_,
_class.access.spec_). ]
3 A class shall not be specified as a direct base class of a derived
class more than once. [Note: a class can be an indirect base class
more than once and can be a direct and an indirect base class. ]
[Example:
class B { /* ... */ };
class D : public B, public B { /* ... */ }; // ill-formed
class L { public: int next; /* ... */ };
class A : public L { /* ... */ };
class B : public L { /* ... */ };
class C : public A, public B { void f(); /* ... */ }; // well-formed
class D : public A, public L { void f(); /* ... */ }; // well-formed
--end example]
4 A base class specifier that does not contain the keyword virtual,
specifies a nonvirtual base class. A base class specifier that con
tains the keyword virtual, specifies a virtual base class. For each
distinct occurrence of a nonvirtual base class in the class lattice of
the most derived class, the most derived object (_intro.object_) shall
contain a corresponding distinct base class subobject of that type.
For each distinct base class that is specified virtual, the most
derived object shall contain a single base class subobject of that
type. [Example: for an object of class type C, each distinct occur
rence of a (non-virtual) base class L in the class lattice of C corre
sponds one-to-one with a distinct L subobject within the object of
type C. Given the class C defined above, an object of class C will
have two sub-objects of class L as shown below.
L L
| |
| |
A B
C
In such lattices, explicit qualification can be used to specify which
subobject is meant. The body of function C::f could refer to the mem
ber next of each L subobject:
void C::f() { A::next = B::next; } // well-formed
Without the A:: or B:: qualifiers, the definition of C::f above would
be ill-formed because of ambiguity (_class.member.lookup_).
5 For another example,
class V { /* ... */ };
class A : virtual public V { /* ... */ };
class B : virtual public V { /* ... */ };
class C : public A, public B { /* ... */ };
for an object c of class type C, a single subobject of type V is
shared by every base subobject of c that is declared to have a virtual
base class of type V. Given the class C defined above, an object of
class C will have one subobject of class V, as shown below.
V
A B
C
6 A class can have both virtual and nonvirtual base classes of a given
type.
class B { /* ... */ };
class X : virtual public B { /* ... */ };
class Y : virtual public B { /* ... */ };
class Z : public B { /* ... */ };
class AA : public X, public Y, public Z { /* ... */ };
For an object of class AA, all virtual occurrences of base class B in
the class lattice of AA correspond to a single B subobject within the
object of type AA, and every other occurrence of a (non-virtual) base
class B in the class lattice of AA corresponds one-to-one with a dis
tinct B subobject within the object of type AA. Given the class AA
defined above, class AA has two sub-objects of class B: Z's B and the
virtual B shared by X and Y, as shown below.
B B
|
|
X Y Z
AA
--end example]
10.2 Member name lookup [class.member.lookup]
1 Member name lookup determines the meaning of a name id-expression) in
a class scope (_basic.scope.class_). Name lookup can result in an
ambiguity, in which case the program is ill-formed. For an id-
expression, name lookup begins in the class scope of this; for a qual
ified-id, name lookup begins in the scope of the nested-name-
specifier. Name lookup takes place before access control
(_basic.lookup_, _class.access_).
2 The following steps define the result of name lookup in a class scope.
First, every declaration for the name in the class and in each of its
base class sub-objects is considered. A member name f in one sub-
object B hides a member name f in a sub-object A if A is a base class
sub-object of B. Any declarations that are so hidden are eliminated
from consideration. If the resulting set of declarations are not all
from sub-objects of the same type, or the set has a nonstatic member
and includes members from distinct sub-objects, there is an ambiguity
and the program is ill-formed. Otherwise that set is the result of
the lookup.
3 [Example:
class A {
public:
int a;
int (*b)();
int f();
int f(int);
int g();
};
class B {
int a;
int b();
public:
int f();
int g;
int h();
int h(int);
};
class C : public A, public B {};
void g(C* pc)
{
pc->a = 1; // error: ambiguous: A::a or B::a
pc->b(); // error: ambiguous: A::b or B::b
pc->f(); // error: ambiguous: A::f or B::f
pc->f(1); // error: ambiguous: A::f or B::f
pc->g(); // error: ambiguous: A::g or B::g
pc->g = 1; // error: ambiguous: A::g or B::g
pc->h(); // ok
pc->h(1); // ok
}
--end example]
4 If the name of an overloaded function is unambiguously found, over
loading resolution (_over.match_) also takes place before access con
trol. Ambiguities can often be resolved by qualifying a name with its
class name. [Example:
class A {
public:
int f();
};
class B {
public:
int f();
};
class C : public A, public B {
int f() { return A::f() + B::f(); }
};
--end example]
5 A static member, a nested type or an enumerator defined in a base
class T can unambiguously be found even if an object has more than one
base class subobject of type T. Two base class subobjects share the
nonstatic member subobjects of their common virtual base classes.
[Example:
class V { public: int v; };
class A {
public:
int a;
static int s;
enum { e };
};
class B : public A, public virtual V {};
class C : public A, public virtual V {};
class D : public B, public C { };
void f(D* pd)
{
pd->v++; // ok: only one `v' (virtual)
pd->s++; // ok: only one `s' (static)
int i = pd->e; // ok: only one `e' (enumerator)
pd->a++; // error, ambiguous: two `a's in `D'
}
--end example]
6 When virtual base classes are used, a hidden declaration can be
reached along a path through the sub-object lattice that does not pass
through the hiding declaration. This is not an ambiguity. The iden
tical use with nonvirtual base classes is an ambiguity; in that case
there is no unique instance of the name that hides all the others.
[Example:
class V { public: int f(); int x; };
class W { public: int g(); int y; };
class B : public virtual V, public W
{
public:
int f(); int x;
int g(); int y;
};
class C : public virtual V, public W { };
class D : public B, public C { void glorp(); };
W V W
B C
D
The names defined in V and the left hand instance of W are hidden by
those in B, but the names defined in the right hand instance of W are
not hidden at all.
void D::glorp()
{
x++; // ok: B::x hides V::x
f(); // ok: B::f() hides V::f()
y++; // error: B::y and C's W::y
g(); // error: B::g() and C's W::g()
}
--end example]
7 An explicit or implicit conversion from a pointer to or an lvalue of a
derived class to a pointer or reference to one of its base classes
shall unambiguously refer to a unique object representing the base
class. [Example:
class V { };
class A { };
class B : public A, public virtual V { };
class C : public A, public virtual V { };
class D : public B, public C { };
void g()
{
D d;
B* pb = &d;
A* pa = &d; // error, ambiguous: C's A or B's A ?
V* pv = &d; // fine: only one V sub-object
}
--end example]
10.3 Virtual functions [class.virtual]
1 Virtual functions support dynamic binding and object-oriented program
ming. A class that declares or inherits a virtual function is called
a polymorphic class.
2 If a virtual member function vf is declared in a class Base and in a
class Derived, derived directly or indirectly from Base, a member
function vf with the same name and same parameter list as Base::vf is
declared, then Derived::vf is also virtual (whether or not it is so
declared) and it overrides1) Base::vf. For convenience we say that
any virtual function overrides itself. Then in any well-formed class,
for each virtual function declared in that class or any of its direct
or indirect base classes there is a unique final overrider that over
rides that function and every other overrider of that function. The
rules for member lookup (_class.member.lookup_) are used to determine
the final overrider for a virtual function in the scope of a derived
class.
_________________________
1) A function with the same name but a different parameter list
(_over_) as a virtual function is not necessarily virtual and does not
override. The use of the virtual specifier in the declaration of an
overriding function is legal but redundant (has empty semantics). Ac
cess control (_class.access_) is not considered in determining over
riding.
3 [Note: a virtual member function does not have to be visible to be
overridden, for example,
struct B {
virtual void f();
};
struct D : B {
void f(int);
};
struct D2 : D {
void f();
};
the function f(int) in class D hides the virtual function f() in its
base class B; D::f(int) is not a virtual function. However, f()
declared in class D2 has the same name and the same parameter list as
B::f(), and therefore is a virtual function that overrides the func
tion B::f() even though B::f() is not visible in class D2. ]
4 Even though destructors are not inherited, a destructor in a derived
class overrides a base class destructor declared virtual; see
_class.dtor_ and _class.free_.
5 A program is ill-formed if the return type of any overriding function
differs from the return type of the overridden function unless the
return type of the latter is pointer or reference (possibly cv-
qualified) to a class B, and the return type of the former is pointer
or reference (respectively) to a class D such that B is an unambiguous
direct or indirect base class of D, accessible in the class of the
overriding function, and the cv-qualification in the return type of
the overriding function is less than or equal to the cv-qualification
in the return type of the overridden function. In that case when the
overriding function is called as the final overrider of the overridden
function, its result is converted to the type returned by the (stati
cally chosen) overridden function (_expr.call_). The return type of
the overriding virtual function shall not be a pointer or reference to
an incomplete class type if it differs from the return type of the
overridden function. [Example:
class B {};
class D : private B { friend class Derived; };
struct Base {
virtual void vf1();
virtual void vf2();
virtual void vf3();
virtual B* vf4();
virtual B* vf5();
void f();
};
struct No_good : public Base {
D* vf4(); // error: B (base class of D) inaccessible
};
class A;
struct Derived : public Base {
void vf1(); // virtual and overrides Base::vf1()
void vf2(int); // not virtual, hides Base::vf2()
char vf3(); // error: invalid difference in return type only
D* vf4(); // okay: returns pointer to derived class
A* vf5(); // error: returns pointer to incomplete class
void f();
};
void g()
{
Derived d;
Base* bp = &d; // standard conversion:
// Derived* to Base*
bp->vf1(); // calls Derived::vf1()
bp->vf2(); // calls Base::vf2()
bp->f(); // calls Base::f() (not virtual)
B* p = bp->vf4(); // calls Derived::pf() and converts the
// result to B*
Derived* dp = &d;
D* q = dp->vf4(); // calls Derived::pf() and does not
// convert the result to B*
dp->vf2(); // ill-formed: argument mismatch
}
--end example]
6 [Note: the interpretation of the call of a virtual function depends on
the type of the object for which it is called (the dynamic type),
whereas the interpretation of a call of a nonvirtual member function
depends only on the type of the pointer or reference denoting that
object (the static type) (_expr.call_). ]
7 [Note: the virtual specifier implies membership, so a virtual function
cannot be a nonmember (_dcl.fct.spec_) function. Nor can a virtual
function be a static member, since a virtual function call relies on a
specific object for determining which function to invoke. A virtual
function declared in one class can be declared a friend in another
class. ]
8 A virtual function declared in a class shall be defined, or declared
pure (_class.abstract_) in that class, or both; but no diagnostic is
required (_basic.def.odr_).
9 [Example: here are some uses of virtual functions with multiple base
classes:
struct A {
virtual void f();
};
struct B1 : A { // note non-virtual derivation
void f();
};
struct B2 : A {
void f();
};
struct D : B1, B2 { // D has two separate A sub-objects
};
void foo()
{
D d;
// A* ap = &d; // would be ill-formed: ambiguous
B1* b1p = &d;
A* ap = b1p;
D* dp = &d;
ap->f(); // calls D::B1::f
dp->f(); // ill-formed: ambiguous
}
In class D above there are two occurrences of class A and hence two
occurrences of the virtual member function A::f. The final overrider
of B1::A::f is B1::f and the final overrider of B2::A::f is B2::f.
10The following example shows a function that does not have a unique
final overrider:
struct A {
virtual void f();
};
struct VB1 : virtual A { // note virtual derivation
void f();
};
struct VB2 : virtual A {
void f();
};
struct Error : VB1, VB2 { // ill-formed
};
struct Okay : VB1, VB2 {
void f();
};
Both VB1::f and VB2::f override A::f but there is no overrider of both
of them in class Error. This example is therefore ill-formed. Class
Okay is well formed, however, because Okay::f is a final overrider.
11The following example uses the well-formed classes from above.
struct VB1a : virtual A { // does not declare f
};
struct Da : VB1a, VB2 {
};
void foe()
{
VB1a* vb1ap = new Da;
vb1ap->f(); // calls VB2:f
}
--end example]
12Explicit qualification with the scope operator (_expr.prim_) sup
presses the virtual call mechanism. [Example:
class B { public: virtual void f(); };
class D : public B { public: void f(); };
void D::f() { /* ... */ B::f(); }
Here, the function call in D::f really does call B::f and not D::f. ]
10.4 Abstract classes [class.abstract]
1 The abstract class mechanism supports the notion of a general concept,
such as a shape, of which only more concrete variants, such as circle
and square, can actually be used. An abstract class can also be used
to define an interface for which derived classes provide a variety of
implementations.
2 An abstract class is a class that can be used only as a base class of
some other class; no objects of an abstract class can be created
except as sub-objects of a class derived from it. A class is abstract
if it has at least one pure virtual function. [Note: such a function
might be inherited: see below. ] A virtual function is specified pure
by using a pure-specifier (_class.mem_) in the function declaration in
the class declaration. A pure virtual function need be defined only
if explicitly called with the qualified-id syntax (_expr.prim_).
[Example:
class point { /* ... */ };
class shape { // abstract class
point center;
// ...
public:
point where() { return center; }
void move(point p) { center=p; draw(); }
virtual void rotate(int) = 0; // pure virtual
virtual void draw() = 0; // pure virtual
// ...
};
--end example] [Note: a function declaration cannot provide both a
pure-specifier and a definition. For example,
struct C {
void f() { }=0; // ill-formed
};
--end note]
3 An abstract class shall not be used as a parameter type, as a function
return type, or as the type of an explicit conversion. Pointers and
references to an abstract class can be declared. [Example:
shape x; // error: object of abstract class
shape* p; // ok
shape f(); // error
void g(shape); // error
shape& h(shape&); // ok
--end example]
4 A class is abstract if it contains or inherits at least one pure vir
tual function for which the final overrider is pure virtual.
[Example:
class ab_circle : public shape {
int radius;
public:
void rotate(int) {}
// ab_circle::draw() is a pure virtual
};
Since shape::draw() is a pure virtual function ab_circle::draw() is a
pure virtual by default. The alternative declaration,
class circle : public shape {
int radius;
public:
void rotate(int) {}
void draw(); // a definition is required somewhere
};
would make class circle nonabstract and a definition of circle::draw()
must be provided. ]
5 [Note: an abstract class can be derived from a class that is not
abstract, and a pure virtual function may override a virtual function
which is not pure. ]
6 Member functions can be called from a constructor (or destructor) of
an abstract class; the effect of making a virtual call
(_class.virtual_) to a pure virtual function directly or indirectly
for the object being created (or destroyed) from such a constructor
(or destructor) is undefined.