请看前面的示例。由于名称 a 是类 A 和类 B 的成员,因此编译器无法辩明哪个 a 指定将调用函数。如果成员可以引用多个函数、对象、类型或枚举数,则对该成员的访问是不明确的。
编译器通过按此顺序执行测试来检测多义性:
如果对名称的访问是不明确的(如上所述),则会生成错误消息。
如果重载函数是明确的,则将解析它们。(有关函数重载多义性的详细信息,请参阅参数匹配。)
如果对名称的访问违背了成员访问权限,则会生成错误消息。(有关详细信息,请参阅成员访问控制。)
在表达式通过继承产生多义性时,您可以通过限定考虑中的名称及其类名来手动消除该多义性。若要适当编译上面的示例而不产生多义性,请使用如下代码:
C *pc = new C;
pc->B::a();
注意
在声明 C 时,如果在 B 的范围内引用 C,则可能会导致出现错误。但不会发出任何错误,直到在 B 的范围内实际创建对 C 的非限定引用。
主导
通过一个继承关系图到达多个名称(函数、对象或枚举器)是可能的。这种情况被视为与非虚拟基类一起使用时目的不明确。这些名称与虚拟基类一起使用时目的不明确,除非其中一个名称“决定”其他名称。
如果某个名称在两个类中定义并且一个类派生自另一个类,则该名称可控制另一个名称。基准名称是派生类中的名称;此名称在本应出现多义性时使用,如以下示例所示:
// deriv_Dominance.cpp
// compile with: /LD
class A {
public:
int a;
};
class B : public virtual A {
public:
int a();
};
class C : public virtual A {};
class D : public B, public C {
public:
D() { a(); } // Not ambiguous. B::a() dominates A::a.
};
不明确的转换
从指向类类型的指针或对类类型的引用的显式或隐式转换可能会导致多义性。下图(指向基类的指针的不明确转换)显示如下内容:
D 类型的对象的声明。
将 address-of 运算符 (&) 应用于该对象的效果。请注意,address-of 运算符总是提供该对象的基址。
将使用 address-of 运算符获取的指针显式转换为基类类型 A 的效果。请注意,将该对象的地址强制转换为 A* 类型并不总是为编译器提供足够的信息,以供 A 类型的子对象进行选择;在这种情况下,将存在两个子对象。










