Pergunta

Eu estava lendo o C ++ 0x FAQ por Stroustrup e ficou preso com este código. Considere o seguinte código

struct A
{
    void f(double)
    {
        std::cout << "in double" << std::endl;
    }
};

struct B : A
{
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};


int main()
{
    A a; a.f(10.10);  // as expected, A.f will get called
    B b; b.f(10.10);  // This calls b.f and we lose the .10 here
    return 0;
}

O meu entendimento foi quando um tipo é herdado, todos os membros protegidas públicas e será acessível a partir da classe derivada. Mas de acordo com este exemplo, parece que eu estou errado. Eu estava esperando o b.f irá chamar classes base f . Eu tenho o resultado esperado, alterando a classe derivada como

struct B : A
{
    using A::f;
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};

Perguntas

  1. Por que não era trabalhar no primeiro código?
  2. Qual a secção do C ++ padrão descreve todas estas regras de escopo?
Foi útil?

Solução

O primeiro código funciona como c ++ é projetado para trabalho.

A sobrecarga resolução segue um conjunto muito complicado de regras. De c do Stroustrup ++ bíblia 15.2.2 "[A] mbiguities entre as funções de diferentes classes de base não são resolvidos com base em tipos de argumentos."

Ele passa a explicar o uso de "usar", como você descreveu.

Esta foi uma decisão de projeto na língua.

I tendem a seguir o livro Stroustrup, em vez do padrão, mas eu tenho certeza que ele está lá.

[Edit]

Aqui está (do padrão):

Capítulo 13

Quando são especificados dois ou mais diferentes declarações para um único nome no mesmo escopo, esse nome é dito ser sobrecarregado.

E, em seguida:

13.2 Declaração de harmonização

1 Duas declarações de função com o mesmo nome referem-se a mesma função se eles estão no mesmo escopo e têm declarações de parâmetros equivalentes (13,1). Um membro função de uma classe de derivados não está no mesmo alcance como um membro de função o mesmo nome em uma classe base.

Outras dicas

É porque A :: f é "escondido" em vez de "sobrecarga" ou "substituído". Consulte:

http://www.parashift.com /c++-faq-lite/strange-inheritance.html#faq-23.9

Pesquise resolução sobrecarga . A semelhante, mas não .

C ++, não há sobrecarga através de espaços, no escopo classes derivadas não são uma excepção. (segundo a C ++ Programming Language)

Para obter mais informações, consulte a http: //www.research. att.com/~bs/bs_faq2.html#overloadderived

No primeiro caso, o método da classe base 'f' é escondida pelo método de classe derivada. Em C ++ não há sobrecarga através âmbitos; é por isso que não é chamado. O padrão C ++ explica todas as regras o nome do membro de pesquisa do seção 10.2 Membro pesquisa de nome [class.member.lookup] . HTH

A primeira versão do código deve realmente chamar B :: f. Você re-definir o símbolo "f" em struct "B", por isso esconde o símbolo original "f" do struct "A". Não é uma sobrecarga, como pode parecer.

Sempre que compilador encontra b.f (), ele procura o struct "B" para um símbolo de "f". Ela está presente lá, então o compilador decide chamar B :: f (int), convertendo duplo para int. Ele não vê necessidade de digitalizar a classe pai para uma função mais adequada ...

No entanto, quando você adicionar "usando Um :: f", é uma directiva explict para o compilador para digitalizar uma classe pai para o símbolo "f". Agora, a classe B tem duas funções sobrecarregadas:. Para int e para double

Acredito também, que você pode escrever B. De :: f () sem usar "usando" directiva no exemplo original ...

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