Remplacerait '::' par '. 'créer des ambiguïtés en C ++?

95

En C ++, l'opérateur ::est utilisé pour accéder aux classes, fonctions et variables dans un espace de noms ou une classe.

Si la spécification de langage utilisée .au lieu de ::dans ces cas aussi, comme lors de l'accès aux variables / méthodes d'instance d'un objet, cela provoquerait-il des ambiguïtés possibles qui ne sont pas présentes ::?

Étant donné que C ++ n'autorise pas les noms de variables qui sont également un nom de type, je ne peux pas penser à un cas où cela pourrait se produire.

Clarification: je ne demande pas pourquoi a ::été choisi ., juste si cela aurait pu fonctionner aussi?

Jimmy RT
la source
Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Samuel Liew

Réponses:

124

En raison des tentatives de rendre C ++ principalement compatible avec le code C existant (qui permet les collisions de noms entre les noms d'objets et les balises struct), C ++ permet les collisions de noms entre les noms de classe et les noms d'objets.

Ce qui signifie que:

struct data {
    static int member;
};

struct data2 {
    int member;
};

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

est un code légitime.

Trousse.
la source
11
Donc, la réponse à la question dans le titre est oui, ce serait le cas , n'est-ce pas?
Enrico Maria De Angelis
2
@EnricoMariaDeAngelis ce n'est pas si simple. Si C ++ était développé comme un langage complètement nouveau, comme Java ou C #, l'ambiguïté pourrait probablement être évitée . Mais C ++ a été développé comme "C avec des classes", et c'est pourquoi ce n'est pas le cas. "Oui, ça va " est une bonne réponse, mais à une question différente.
Kit.
Attendez, la ligne d'affectation ne montre-t-elle pas simplement que mettre .ou ::entre les deux mêmes "mots" a un effet différent (se data.memberréfère à memberl' dataobjet de la classe data2, alors qu'il se data::memberréfère à la memberde la classe data)?
Enrico Maria De Angelis
1
Oui, mais ce n'est pas quelque chose dont les concepteurs de langage devraient être fiers. C'est juste un artefact des décisions de compatibilité.
Kit.
Ok, je comprends que la façon dont C ++ est aujourd'hui et a été jusqu'à présent dépend également de ce qu'était C au moment où C ++ en est issu. Mais en parlant du C ++ tel qu'il est, et en laissant de côté pourquoi il est tel qu'il est, il y aurait une ambiguïté si tout ::était changé en .. D'une certaine manière, vous avez déjà répondu oui . Je ne peux tout simplement pas percer votre premier commentaire. Peut-être que mon niveau fait que ce commentaire me semble enfumé.
Enrico Maria De Angelis
37

Un exemple où les deux sont valides, mais font référence à des objets différents:

#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';
}

Voir en direct sur coliru .

Déduplicateur
la source
Et celui-ci ne pouvait pas être facilement résolu avec différentes décisions de conception!
user253751
7

Il existe une différence entre a::bet a.b::implique celui autilisé comme espace de noms, ce qui signifie qu'il s'agit d'un espace de noms ou d'un nom de type. À condition que C ++ prenne en charge l'héritage pluriel non virtuel et qu'une variable puisse avoir le même nom qu'un type, cela supprime les chances de référencer un mauvais objet. Il est nécessaire pour la métaprogrammation des modèles.

Un autre exemple serait &B::foovs &B.foodans le contexte de la classe B.

Swift - Friday Pie
la source
2

Prenons l'exemple de @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.
}

En direct sur Coliru Viewer

N'ayant pas la possibilité de différencier à l'aide de ::, le membre auquel nous voulons accéder, il est impossible d'accéder aux membres déclarés dans une classe parente avec des noms identiques.

SM
la source
A A(le nom de variable qui est également un nom de type) n'est cependant pas valide en C ++, donc cet exemple ne fonctionne pas pour l'instant
Jimmy RT
1
@ JimmyR.T. Il y a l'exemple de la vie professionnelle sur Coliru Viewer. Confirmez votre déclaration s'il vous plaît avec un paragraphe de la norme.
SM
si l'on ajoutait le diamant d'héritage maudit ici avec la même chose de l'autre côté, ce serait un sommet de nommer la schizophrénie possible en C ++
Swift - Friday Pie