二义性适用于任何名字 包括函数名
如果一个类有多个直接基类
就可以共享这些基类中那些同名的成员函数
如果要调用这些成员函数中的一个
那么编译器将不知道调用它们之中的哪一个
//: C09:AmbiguousName.cpp {-xo}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
class Top {
public:
virtual ~Top() {}
};
class Left : virtual public Top {
public:
void f() {}
};
class Right : virtual public Top {
public:
void f() {}
};
class Bottom : public Left, public Right {};
int main() {
Bottom b;
b.f(); // Error here
} ///:~
类Bottom已经继承了两个同名的函数
并且没有办法在它们之间进行选择
通常消除二义性调用的方法
以基类名来限定函数的调用
//: C09:BreakTie.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
class Top {
public:
virtual ~Top() {}
};
class Left : virtual public Top {
public:
void f() {}
};
class Right : virtual public Top {
public:
void f() {}
};
class Bottom : public Left, public Right {
public:
using Left::f;
};
int main() {
Bottom b;
b.f(); // Calls Left::f()
} ///:~
无输出
现在Bottom的作用域可以找到名字Left::f
所以完全不用考虑名字Right::f的查找问题
在一个层次结构中的不同分支上存在同名函数常常发生冲突
继承层次结构不存在这样的问题
//: C09:Dominance.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
class Top {
public:
virtual ~Top() {}
virtual void f() {}
};
class Left : virtual public Top {
public:
void f() {}
};
class Right : virtual public Top {};
class Bottom : public Left, public Right {};
int main() {
Bottom b;
b.f(); // Calls Left::f()
} ///:~
程序在这里没有显式调用Right::f()
因为Left::f()是位于层次结构的最高层派生类
所以对b.f()语句的执行将调用Left::f()
在同名的两个函数之间进行选择时
编译器将选择占优势的那个函数
如果没有占优势的名字
会产生二义性
//: C09:Dominance2.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
#include <iostream>
using namespace std;
class A {
public:
virtual ~A() {}
virtual void f() { cout << "A::f\n"; }
};
class B : virtual public A {
public:
void f() { cout << "B::f\n"; }
};
class C : public B {};
class D : public C, virtual public A {};
int main() {
B* p = new D;
p->f(); // Calls B::f()
delete p;
getchar();
} ///:~
输出
B::f
类A是类B的基类
所以名字B::f比名字A::f占优势