Neste exemplo, classes Foo
e Bar
são fornecidas a partir de uma biblioteca. Minha classe Baz
herda de ambos.
struct Foo
{
void do_stuff (int, int);
};
struct Bar
{
virtual void do_stuff (float) = 0;
};
struct Baz : public Foo, public Bar
{
void func ()
{
do_stuff (1.1f); // ERROR HERE
}
};
struct BazImpl : public Baz
{
void do_stuff (float) override {};
};
int main ()
{
BazImpl () .func ();
}
Recebo o erro de compilação reference to ‘do_stuff’ is ambiguous
que parece falso para mim, pois as duas assinaturas de funções são totalmente diferentes. Se do_stuff
não fosse virtual, eu poderia ligar Bar::do_stuff
para desambiguá-lo, mas fazer isso quebra o polimorfismo e causa um erro no vinculador.
Posso fazer func
chamadas para o virtual do_stuff
sem renomear as coisas?
Respostas:
Você consegue fazer isso:
Testado com o wandbox gcc mais recente e compila bem. Eu acho que é o mesmo caso com sobrecargas de função, uma vez que você sobrecarrega um, você não pode usar implementações de classe base sem
using
.De fato, isso não tem nada a ver com funções virtuais. O exemplo a seguir tem o mesmo erro
GCC 9.2.0 error: reference to 'do_stuff' is ambiguous
:Possível questão relacionada
fonte
A pesquisa de nome e a resolução de sobrecarga são diferentes. O nome deve ser encontrado em um escopo primeiro, ou seja, precisamos encontrar um
X
para que o nomedo_stuff
seja resolvido paraX::do_stuff
- independentemente do uso do nome - e, em seguida, a resolução de sobrecarga selecione entre as diferentes declarações deX::do_stuff
.O processo não é identificar todos esses casos
A::do_stuff
,B::do_stuff
etc., que são visíveis, e depois executar a resolução de sobrecarga entre a união do que isso. Em vez disso, um único escopo deve ser identificado para o nome.Neste código:
Baz
não contém o nomedo_stuff
, portanto, as classes base podem ser consultadas. Mas o nome ocorre em duas bases diferentes, portanto, a pesquisa de nome falha ao identificar um escopo. Nunca chegamos a uma resolução de sobrecarga.A correção sugerida na outra resposta funciona porque introduz o nome
do_stuff
no escopo deBaz
e também introduz 2 sobrecargas para o nome. Portanto, a pesquisa de nome determina o quedo_stuff
significaBaz::do_stuff
e, em seguida, a resolução de sobrecarga seleciona as duas funções conhecidas comoBaz::do_stuff
.Além disso, o sombreamento é outra consequência da pesquisa de nome (não uma regra em si). A pesquisa de nome seleciona o escopo interno e, portanto, qualquer coisa no escopo externo não corresponde.
Um outro fator complicador ocorre quando a pesquisa dependente de argumento está em jogo. Para resumir muito brevemente, a pesquisa de nome é feita várias vezes para uma chamada de função com argumentos do tipo de classe - a versão básica, conforme descrito na minha resposta, e novamente para o tipo de argumento. Em seguida, a união dos escopos encontrados entra no conjunto de sobrecargas. Mas isso não se aplica ao seu exemplo, pois sua função possui apenas parâmetros do tipo interno.
fonte