Substituir '::' por '. criar ambiguidades em C ++?

95

No C ++, o operador ::é usado para acessar classes, funções e variáveis ​​em um espaço para nome ou classe.

Se a especificação de linguagem usada em .vez de ::nesses casos também gostar ao acessar variáveis ​​/ métodos de instância de um objeto, isso causaria possíveis ambiguidades que não estão presentes ::?

Dado que o C ++ não permite nomes de variáveis ​​que também são um nome de tipo, não consigo pensar em um caso em que isso poderia acontecer.

Esclarecimento: Não estou perguntando por que ::foi escolhido ., apenas se poderia ter funcionado também?

Jimmy RT
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Samuel Liew

Respostas:

124

Devido a tentativas de tornar o C ++ principalmente compatível com o código C existente (que permite colisões de nomes entre nomes de objetos e tags struct), o C ++ permite colisões de nomes entre nomes de classes e nomes de objetos.

O que significa que:

struct data {
    static int member;
};

struct data2 {
    int member;
};

void f(data2& data) {
    data.member = data::member;
}

é um código legítimo.

Kit.
fonte
11
Portanto, a resposta para a pergunta no título é Sim, seria , não é?
Enrico Maria De Angelis
2
@EnricoMariaDeAngelis não é assim tão simples. Se o C ++ fosse desenvolvido como uma linguagem completamente nova, como Java ou C #, a ambiguidade provavelmente poderia ser evitada . Mas o C ++ foi desenvolvido como "C com classes", e é por isso que não é. "Sim, será " é uma resposta correta, mas para uma pergunta diferente.
Kit.
Espere, não é a linha de atribuição apenas mostrando que colocar .ou ::entre os mesmos dois "palavras" tem efeito diferente ( data.memberrefere-se à memberdo dataobjeto da classe data2, ao passo que data::memberse refere ao memberda classe data)?
Enrico Maria De Angelis
11
Sim, mas não é algo que os designers de idiomas devam se orgulhar. É apenas um artefato de decisões de compatibilidade.
Kit.
Ok, eu entendo que a forma como o C ++ é hoje e tem sido até agora (também) depende do que C era no momento em que o C ++ se desenvolveu a partir dele. Mas falando do C ++ como é e deixando de lado por que é como é, haveria uma ambiguidade se todos ::fossem alterados para .. De certa forma, você já respondeu sim . Simplesmente não posso violar seu primeiro comentário. Talvez meu nível faça esse comentário parecer esfumaçado para mim.
Enrico Maria De Angelis
37

Um exemplo em que ambos são válidos, mas referem-se a objetos diferentes:

#include <iostream>

struct A {
    int i;
};

struct B {
    int i;
    A B;
};

int main() {
    B x {0, 1};
    std::cout << x.B.i << '\n';
    std::cout << x.B::i << '\n';
}

Veja ao vivo em coliru .

Desduplicador
fonte
E este não poderia ser facilmente resolvido com diferentes decisões de design!
user253751 3/02
7

Há diferença entre a::be a.bonde ::implica quea usado como espaço para nome, o que significa que é espaço para nome ou nome do tipo. Desde que o C ++ ofereça suporte a herança plural não virtual e que uma variável possa ter o mesmo nome que um tipo, isso reduz as chances de fazer referência a objetos incorretos. É necessário para a metaprogramação de modelos.

Outro exemplo seria &B::foovs &B.foono contexto da classe B.

Swift - torta de sexta-feira
fonte
2

Vamos estender o exemplo do @Deduplicator:

#include <iostream>

struct A {
    int i;
};

struct B : public A {
    int i;
    A A;
};

int main() {
    B x {1, 2};
    std::cout << x.i << '\n';
    std::cout << x.B::i << '\n';  // The same as the line above.
    std::cout << x.A.i << '\n';
    std::cout << x.A::i << '\n';  // Not the same as the line above.
}

Ao vivo no Coliru Viewer

Não tendo a possibilidade de diferenciar com a ajuda de ::, qual membro queremos acessar, é impossível acessar membros declarados em uma classe pai com nomes idênticos.

SM
fonte
A A(nome da variável que também é um nome de tipo) não é válido em C ++, portanto, este exemplo não funciona por enquanto
Jimmy RT
11
@ JimmyR.T. Há o exemplo da vida profissional no Coliru Viewer. Confirme sua declaração com um parágrafo da norma.
SM
se alguém adicionasse o diamante de herança amaldiçoada aqui com a mesma coisa do outro lado, seria um pináculo de nomear a esquizofrenia possível em C ++
Swift - sexta-feira