Dzieje się tak, ponieważ wyszukiwanie nazw zatrzymuje się, jeśli znajdzie nazwę w jednej z twoich baz. W innych bazach nie będzie wyglądać dalej. Funkcja w B pomocniczym funkcję w A. należy ponownie zadeklarować funkcję w zakresie b, tak, że obie te funkcje są widoczne od wewnątrz B i C:
class A
{
public:
void foo(string s){};
};
class B : public A
{
public:
int foo(int i){};
using A::foo;
};
class C : public B
{
public:
void bar()
{
string s;
foo(s);
}
};
Edycja: rzeczywisty opis podany przez standard to (od 10.2 / 2):
Poniższe kroki definiują wynik wyszukiwania nazwy w zakresie klasy, C. Po pierwsze, brana jest pod uwagę każda deklaracja nazwy w klasie i każdym z jej podobiektów klasy bazowej. Nazwa elementu f w jednym podobiekcie B ukrywa nazwę elementu f w podobiekcie A, jeśli A jest podobiektem klasy bazowej B. Wszelkie deklaracje, które są tak ukryte, są eliminowane z rozważań. Każda z tych deklaracji, która została wprowadzona przez deklarację using, jest uważana za pochodzącą z każdego podobiektu C, który jest typu zawierającego deklarację wyznaczoną przez deklarację using. 96) Jeśli wynikowy zestaw deklaracji nie jest wszystkie z podobiektów tego samego typu lub zbiór ma niestatycznego członka i zawiera elementy składowe z różnych podobiektów, występuje niejednoznaczność i program jest źle sformułowany. W przeciwnym razie ten zestaw jest wynikiem wyszukiwania.
W innym miejscu (tuż nad nim) ma do powiedzenia:
W przypadku wyrażenia id [ coś w rodzaju „foo” ], wyszukiwanie nazw zaczyna się w zakresie klasy this; dla kwalifikowanego identyfikatora [ coś w rodzaju „A :: foo”, A jest zagnieżdżonym specyfikatorem-nazwy ], wyszukiwanie nazw zaczyna się w zakresie zagnieżdżonego specyfikatora-nazwy. Wyszukiwanie nazwy ma miejsce przed kontrolą dostępu (3.4, klauzula 11).
([...] podane przeze mnie). Zauważ, że oznacza to, że nawet jeśli twoje foo w B jest prywatne, foo w A nadal nie zostanie znalezione (ponieważ kontrola dostępu ma miejsce później).