Pergunta

Recentemente chamou minha atenção que as funções-membro completamente sombra funções gratuitas com o mesmo nome quando dentro da classe.E com completamente quero dizer que toda função livre com o mesmo nome não é considerada para resolução de sobrecarga.Eu posso entender por que isso é feito com algo assim:

void f();

struct S
{
    void f();

    void g()
    {
        f(); // calls S::f instead of ::f
    }
};

onde as funções têm assinaturas idênticas, é natural que o escopo das variáveis ​​funcione da mesma maneira.Mas por que proibir chamadas inequívocas onde a função livre tem assinatura diferente como esta:

void f();

struct S
{
    void f(int x);

    void g()
    {
        f(); // fails to compile attempting to call S::f, which has wrong signature
    }
};

Não estou perguntando como ligar para um sombreado função livre de dentro da classe.O que eu quero saber é a lógica por trás desse design.

Foi útil?

Solução

Para pesquisa de nome não qualificado, apenas um escopo por vez é considerado e, se a pesquisa nesse escopo não produzir nenhum resultado, o próximo escopo superior será pesquisado.No seu caso, apenas So escopo de é pesquisado.

Mas por que proibir chamadas inequívocas onde a função livre tem assinatura diferente como esta:

O problema é que pesquisa de nome não se preocupa com nada além do nome, do identificador.Ele ignora completamente o fato de que você deseja chamar uma função, apenas vê um identificador.A mesma pesquisa de nome acontece se você apenas usar auto x = f;, e se você pensar dessa forma, há bons motivos para você querer apenas um escopo muito limitado de pesquisa.Qualquer outra coisa apenas surpreenderia o usuário.

Outras dicas

Existe uma regra especial e muito surpreendente (mas não se aplica ao seu exemplo) que afirma que uma vez nome do membro da classe for encontrado pela pesquisa de nome, nenhum escopo de namespace será pesquisado:

#include <string>

struct C {
    std::string s;

    explicit C (std::string);

    void swap (C& rhs) {
        swap (s, rhs.s); // error: swap is C::swap
    }   
};

void swap (C& lhs, C& rhs) {
    swap (lhs.s, rhs.s); // std::swap(string,string)
}

IMO, isso é uma loucura.

Mas por que proibir chamadas inequívocas onde a função livre tem assinatura diferente como esta:

A pesquisa de nome acontece antes de sobrecarregar a resolução:

  • Se a pesquisa for ambígua, a resolução de sobrecarga não será feita.
  • Se nenhuma função viável for encontrada pela pesquisa de nome, nenhuma outra rodada de pesquisa será tentada.

O as regras são suficientemente complexas sem "feedback" entre sobrecarga e pesquisa de nome.Eu sugeriria simplificação (como remover a regra de nome de escopo de namespace oculto de membro e remover pesquisa de nome ambíguo) em vez de complexificação.

Não posso fornecer uma resposta confiável (talvez alguns se lembrem de uma citação de Design and Evolution of C++ ou realmente esteve no comitê naquela época), mas meu primeiro palpite seria falhar exatamente nos casos como você mostra.É fácil esquecer quantas coisas estão no escopo em um determinado momento.Além disso, a resolução de sobrecarga pode ser bastante complexa e pode haver argumentos e conversões padrão.Portanto, prefiro ter o escopo mais limitado nesse caso para ter sempre certeza do que exatamente está sendo chamado.

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