È perché la ricerca del nome si interrompe se trova un nome in una delle tue basi. Non guarderà oltre in altre basi. La funzione in B ombreggia la funzione in A. Devi dichiarare nuovamente la funzione di A nell'ambito di B, in modo che entrambe le funzioni siano visibili dall'interno di B e 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);
}
};
Modifica: la descrizione reale fornita dallo Standard è (da 10.2 / 2):
I passaggi seguenti definiscono il risultato della ricerca del nome in un ambito di classe, C. Innanzitutto, viene considerata ogni dichiarazione per il nome nella classe e in ciascuno dei suoi sottooggetti della classe base. Un nome membro f in un oggetto secondario B nasconde un nome membro f in un oggetto secondario A se A è un oggetto secondario della classe base di B. Qualsiasi dichiarazione così nascosta viene eliminata dalla considerazione. Ciascuna di queste dichiarazioni che è stata introdotta da una dichiarazione d'uso è considerata provenire da ogni sottooggetto di C che è del tipo contenente la dichiarazione designata dalla dichiarazione d'uso.96) Se l'insieme di dichiarazioni risultante non è tutto da sotto-oggetti dello stesso tipo, o l'insieme ha un membro non statico e include membri da sotto-oggetti distinti, c'è un'ambiguità e il programma è mal formato. Altrimenti quel set è il risultato della ricerca.
Ha quanto segue da dire in un altro posto (appena sopra):
Per un'espressione id [ qualcosa come "foo" ], la ricerca del nome inizia nell'ambito della classe di this; per un id-qualificato [ qualcosa come "A :: foo", A è uno specificatore-nome-annidato ], la ricerca del nome inizia nell'ambito dell'identificatore-nome-annidato. La ricerca del nome avviene prima del controllo dell'accesso (3.4, clausola 11).
([...] messo da me). Nota che significa che anche se il tuo foo in B è privato, il foo in A non verrà comunque trovato (perché il controllo dell'accesso avviene in seguito).