C++中没有像Python一样的MRO。如果一个方法有歧义,编译时会出错。无论一个方法是否是虚拟的都不会影响它,但是虚拟继承会影响它。
该算法在C++标准的第10.2节[class.member.lookup]中描述。基本上它会在超类图中找到最接近的明确实现。该算法的工作原理如下:
假设你要在类C中查找函数f。
我们定义一个名为S(f, C)的查找集,它是一个包含所有可能性的(Δ, Σ)对。 (§10.2/3)
集合Δ称为声明集,它基本上是所有可能的f。
集合Σ称为子对象集,其中包含这些f所在的类。
如果有的话,在C中直接定义(或using
)的所有f都包含在S(f, C)中。(§10.2/4)
Δ = {f in C};
if (Δ != empty)
Σ = {C};
else
Σ = empty;
S(f, C) = (Δ, Σ);
如果S(f, C)为空(§10.2/5),
if (S(f, C) == (empty, empty)) {
B = base classes of C;
for (Bi in B)
S(f, C) = S(f, C) .Merge. S(f, Bi);
}
最终,声明集作为名称解析的结果返回 (§10.2/7)。
return S(f, C).Δ;
将两个查找集 (Δ1, Σ1) 和 (Δ2, Σ2) 的合并定义为 (§10.2/6):
- 如果Σ1中的每个类都是Σ2中至少一个类的基类,则返回(Δ2, Σ2)。
(反之亦然。)
- 否则,如果 Δ1 ≠ Δ2,则返回(ambiguous, Σ1 ∪ Σ2)。
否则,返回(Δ1, Σ1 ∪ Σ2)
function Merge ( (Δ1, Σ1), (Δ2, Σ2) ) {
function IsBaseOf(Σp, Σq) {
for (B1 in Σp) {
if (not any(B1 is base of C for (C in Σq)))
return false;
}
return true;
}
if (Σ1 .IsBaseOf. Σ2) return (Δ2, Σ2);
else if (Σ2 .IsBaseOf. Σ1) return (Δ1, Σ1);
else {
Σ = Σ1 union Σ2;
if (Δ1 != Δ2)
Δ = ambiguous;
else
Δ = Δ1;
return (Δ, Σ);
}
}
例如(§10.2/10),
struct V { int f(); };
struct W { int g(); };
struct B : W, virtual V { int f(); int g(); };
struct C : W, virtual V { };
struct D : B, C {
void glorp () {
f();
g();
}
};
我们计算出
S(f, D) = S(f, B from D) .Merge. S(f, C from D)
= ({B::f}, {B from D}) .Merge. S(f, W from C from D) .Merge. S(f, V)
= ({B::f}, {B from D}) .Merge. empty .Merge. ({V::f}, {V})
= ({B::f}, {B from D})
而且
S(g, D) = S(g, B from D) .Merge. S(g, C from D)
= ({B::g}, {B from D}) .Merge. S(g, W from C from D) .Merge. S(g, V)
= ({B::g}, {B from D}) .Merge. ({W::g}, {W from C from D}) .Merge. empty
= (ambiguous, {B from D, W from C from D})