Tenho uma função com o mesmo nome, mas com assinatura diferente em classes base e derivadas. Quando estou tentando usar a função da classe base em outra classe que herda da derivada, recebo um erro. Veja o seguinte código:
class A
{
public:
void foo(string s){};
};
class B : public A
{
public:
int foo(int i){};
};
class C : public B
{
public:
void bar()
{
string s;
foo(s);
}
};
Recebo o seguinte erro do compilador gcc:
In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)
Se eu remover int foo(int i){};
da classe B
ou renomear foo1
, tudo funcionará bem.
Qual é o problema disso?
Respostas:
Funções em classes derivadas que não substituem funções em classes base, mas que têm o mesmo nome, irão ocultar outras funções com o mesmo nome na classe base.
É geralmente considerado uma prática ruim ter funções em classes derivadas que têm o mesmo nome de funções na classe de baixo, que não têm a intenção de substituir as funções da classe base, pois o que você está vendo geralmente não é o comportamento desejável. Geralmente é preferível dar nomes diferentes a funções diferentes.
Se você precisar chamar a função de base, você precisará definir o escopo da chamada usando
A::foo(s)
. Observe que isso também desabilitaria qualquer mecanismo de função virtualA::foo(string)
ao mesmo tempo.fonte
É porque a pesquisa de nome para se encontrar um nome em uma de suas bases. Não vai olhar além em outras bases. A função em B obscurece a função em A. Você deve declarar novamente a função de A no escopo de B, de modo que ambas as funções sejam visíveis de dentro de B e C:
Editar: A descrição real que o Padrão fornece é (de 10.2 / 2):
Tem o seguinte a dizer em outro lugar (logo acima):
([...] colocado por mim). Note que isso significa que mesmo se seu foo em B for privado, o foo em A ainda não será encontrado (porque o controle de acesso acontece mais tarde).
fonte
void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in
classe B 'por causa do método local `int B :: foo (int)' com o mesmo nome. Talvez seja porque eu uso uma versão antiga do gcc