Pergunta

Eu tenho uma função com o mesmo nome, mas com assinatura diferente em uma base e classes derivadas. Quando eu estou tentando usar a função da classe base em outra classe que herda da derivada, eu 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);
    }
};

Eu 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){}; de B classe, ou se eu mudar o nome de foo1, tudo funciona bem.

Qual é o problema com isso?

Foi útil?

Solução

Funções em classes derivadas que não substituem funções na classe base, mas que tem o mesmo nome hide outras funções com o mesmo nome na classe base.

É geralmente considerado uma má prática ter ter funções em classes derivadas, que têm o mesmo nome de funções na classe baixa que não se destinam a substituir as funções de classe de base como o que você está vendo não é geralmente um comportamento desejável. Geralmente é preferível dar diferentes funções diferentes nomes.

Se você precisa chamar a função de base você precisará âmbito da chamada usando A::foo(s). Note-se que isso também iria desativar qualquer mecanismo de função virtual para A::foo(string) ao mesmo tempo.

Outras dicas

É porque pesquisa de nome pára se encontrar um nome em uma das suas bases. Ele não vai olhar para além de outras bases. A função no B sombras a função em A. Você tem que re-declarar a função de A no âmbito do B, de modo que ambas as funções são visíveis de dentro 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);
    }
};

Edit: A descrição real do padrão dá é (de 10,2 / 2):

As seguintes etapas definir o resultado da pesquisa de nome em um escopo de classe, C. Primeiro, cada declaração para o nome na classe e em cada um dos seus sub-objectos de classe base é considerado. Um nome membro f em um sub objecto B esconde um nome de f membro em um sub-objeto A se A é uma classe de sub-base objeto de B. Qualquer declaração que são tão ocultas são eliminados da consideração. Cada uma dessas declarações que foi introduzido por um utilizando-declaração é considerado a partir de cada sub-objeto de C, que é do tipo que contém o decla- ção designado pelo usando-declaration.96) Se o conjunto resultante de declarações não são todas da sub-objectos do mesmo tipo, ou o conjunto tem um membro não-estático e inclui membros de sub-objectos distintos, existe uma ambigüidade eo programa está mal-formado. Caso contrário, esse conjunto é o resultado da pesquisa.

Tem o seguinte a dizer em outro lugar (logo acima dele):

Para uma expressão id [ algo como "foo" ], pesquisa de nome começa no âmbito classe deste; para um-id qualificada [ algo como "A :: foo", A é um nome de nested-especificador ], pesquisa de nome começa no âmbito do nested-name-especificador. pesquisa de nome ocorre antes de controle de acesso (3.4, cláusula 11).

([...] colocar por mim). Note-se que significa que mesmo se o seu foo em B é privado, o foo em A ainda não serão encontrados (porque o controle de acesso acontece mais tarde).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top