In an inheritance graph containing virtual base classes, a name that can be reached through more than one path is accessed through the path that gives the most access.
For example:
class L { public: void f(); }; class B1 : private virtual L { /* ... */ }; class B2 : public virtual L { /* ... */ }; class D : public B1, public B2 { public: void f() {L::f();} // L::f() is accessed through B2 // and is public };
In the above example, the function f() is accessed through class B2. Because class B2 is inherited publicly and class B1 is inherited privately , class B2 offers more access.
An accessible base class is a publicly derived base class that is neither hidden nor ambiguous in the inheritance hierarchy.
When you derive classes, ambiguities can result if base and derived classes have members with the same names. Access to a base class member is ambiguous if you use a name or qualified name that does not refer to a unique function, object, type, or enumerator. The declaration of a member with an ambiguous name in a derived class is not an error. The ambiguity is only flagged as an error if you use the ambiguous member name.
For example, if two base classes have a member of the same name, an attempt to access the member by the derived class is ambiguous. You can resolve ambiguity by qualifying a member with its class name using the :: (scope resolution ) operator.
The compiler checks for ambiguities at compile time. Because ambiguity checking occurs before access control or type checking, ambiguities may result even if only one of several members with the same name is accessible from the derived class.
Conversions (either implicit or explicit) from a derived class
pointer or reference to a base class pointer or reference must
refer unambiguously to the same accessible base class object. For
example:
class W { /* ... */ }; class X : public W { /* ... */ }; class Y : public W { /* ... */ }; class Z : public X, public Y { /* ... */ }; void main () { Z z; X* xptr = &z; // valid Y* yptr = &z; // valid W* wptr = &z; // error, ambiguous reference to class W // X's W or Y's W ? }
You can use virtual base classes to avoid ambiguous reference.
For example:
class W { /* ... */ }; class X : public virtual W { /* ... */ }; class Y : public virtual W { /* ... */ }; class Z : public X, public Y { /* ... */ }; void main () { Z z; X* xptr = &z; // valid Y* yptr = &z; // valid W* wptr = &z; // valid, W is virtual therefore only one // W subobject exists }
Virtual Base Classes
Multiple Inheritance
Scope Resolution Operator
Derivation
Member Access
Example of Resolving Ambiguous
Access