Name Ambiguities

Multiple inheritance introduces the possibility for names to be inherited along more than one path. The class-member names along these paths are not necessarily unique. These name conflicts are called "ambiguities."

Any expression that refers to a class member must make an unambiguous reference. The following example shows how ambiguities develop:

// deriv_NameAmbiguities.cpp
// compile with: /LD
// Declare two base classes, A and B.
class A {
public:
    unsigned a;
    unsigned b();
};

class B {
public:
    unsigned a();  // Note that class A also has a member "a"
    int b();       //  and a member "b".
    char c;
};

// Define class C as derived from A and B.
class C : public A, public B {};

Given the preceding class declarations, code such as the following is ambiguous because it is unclear whether b refers to the b in A or in B:

C *pc = new C;

pc->b();

Consider the preceding example. Because the name a is a member of both class A and class B, the compiler cannot discern which a designates the function to be called. Access to a member is ambiguous if it can refer to more than one function, object, type, or enumerator.

The compiler detects ambiguities by performing tests in this order:

  1. If access to the name is ambiguous (as just described), an error message is generated.

  2. If overloaded functions are unambiguous, they are resolved. (For more information about function overloading ambiguity, see Argument Matching.)

  3. If access to the name violates member-access permission, an error message is generated. (For more information, see Member-Access Control.)

When an expression produces an ambiguity through inheritance, you can manually resolve it by qualifying the name in question with its class name. To make the preceding example compile properly with no ambiguities, use code such as:

C *pc = new C;

pc->B::a();

Note

When C is declared, it has the potential to cause errors when B is referenced in the scope of C. No error is issued, however, until an unqualified reference to B is actually made in C's scope.

See Also

Reference

Multiple Base Classes