В C ++ нет таких MRO, как Python. Если метод неоднозначный, это ошибка времени компиляции. Виртуальный или нет метод не влияет на него, но виртуальное наследование будет.
Алгоритм описан в стандарте C ++ & sect; [class.member.lookup] (10.2). По сути, он найдет ближайшую однозначную реализацию в графе суперкласса. Алгоритм работает так:
Предположим, вы хотите найти функцию f в классе C .
Мы определяем поисковый набор S (f, C) , представляющий собой пару наборов ( & Delta; , & Sigma ; ) представляет все возможности. (& раздел; 10.2 / 3) * +1028 *
Набор & Delta; называется набором объявлений , который, по сути, является всеми возможными f .
Набор & Sigma; называется набором подобъектов , который содержит классы, в которых находятся эти f .
Пусть S (f, C) включает все f , определенные непосредственно (или using
-ed) в C , если таковые имеются (& раздел; 10.2 / 4) : * * тысяча шестьдесят-три
Δ = {f in C};
if (Δ != empty)
Σ = {C};
else
Σ = empty;
S(f, C) = (Δ, Σ);
Если S (f, C) пусто (& sect; 10.2 / 5) ,
Вычислить S (f, B i ) , где B i - базовый класс C , для всех i .
Слияние каждого S (f, B i ) в S (f, C) по одному.
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);
}
Наконец, набор объявлений возвращается в результате разрешения имени (& sect; 10.2 / 7) .
return S(f, C).Δ;
Слияние двух справочных наборов ( & Delta; 1 , & Sigma; 1 ) и ( & Delta; 2 , & Sigma; 2 ) определяется как (& sect; 10.2 / 6) :
- Если каждый класс в Σ 1 является базовым классом хотя бы одного класса в Σ 2 , вернуть ( & Delta; 2 , Σ 2 ).
(Аналогично для обратного.)
- Иначе, если Δ 1 ≠ Δ 2 , возврат ( неоднозначный , Σ 1 & cup; Σ 2 ).
В противном случае вернуть ( Δ 1 , Σ 1 & cup; Σ 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 (Δ, Σ);
}
}
Например (& sect; 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}) // fine, V is a base class of B.
и
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}) // the W from C is unrelated to B.