95

In C++, the operator :: is used to access classes, functions and variables in a namespace or class.

If the language specification used . instead of :: in those cases too like when accessing instance variables/methods of an object then would that cause possible ambiguities that aren't present with ::?

Given that C++ doesn't allow variable names that are also a type name, I can't think of a case where that could happen.

Clarification: I'm not asking why :: was chosen over ., just if it could have worked too?

Ardent Coder
  • 3,777
  • 9
  • 27
  • 53
Jimmy R.T.
  • 1,314
  • 1
  • 10
  • 13
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/207134/discussion-on-question-by-jimmy-r-t-would-replacing-with-create-am). – Samuel Liew Feb 04 '20 at 01:11

4 Answers4

125

Due to attempts to make C++ mostly compatible with the existing C code (which allows name collisions between object names and struct tags), C++ allows name collisions between class names and object names.

Which means that:

struct data {
    static int member;
};

struct data2 {
    int member;
};

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

is legit code.

Kit.
  • 2,386
  • 1
  • 12
  • 14
  • 11
    So the answer to the question in the title is _Yes, it would_, isn't it? – Enlico Feb 01 '20 at 20:37
  • 2
    @EnricoMariaDeAngelis it's not that simple. Were C++ developed as a completely new language, like Java or C#, the ambiguity _could probably be avoidable_. But C++ was developed as "C with classes", and that's why it's not. "Yes, it _will_" is a correct answer, but to a different question. – Kit. Feb 01 '20 at 20:58
  • Wait, isn't the assignment line just showing that putting `.` or `::` between the same two "words" has different effect (`data.member` refers to the `member` of the `data` object of class `data2`, whereas `data::member` refers to the `member` of the class `data`)? – Enlico Feb 01 '20 at 21:03
  • 1
    Yes, but it's not something that language designers should be proud of. It's just an artifact of compatibility decisions. – Kit. Feb 01 '20 at 21:19
  • Ok, I understand that how C++ is today and has been so far (also) depends on what C was at the time C++ developed from it. But talking of C++ as it is, and leaving aside why it is as it is, there would an ambiguity if all `::` were changed to `.`. In a way you answered _yes_ already. I simply cannot breach into you first comment. Maybe my level makes that comment look smoky to me. – Enlico Feb 01 '20 at 21:27
  • The "compatibiliy decision" *is* something that the language designers are very particular about. Not always so about the outcome, but the principle has been very important in the success of C++. – Wouter van Ooijen Feb 02 '20 at 21:27
38

An example where both are valid, but refer to different objects:

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

See live on coliru.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
7

There is difference between a::b and a.b where :: implies that a used as namespace, which means that it is namespace or typename. Provided that C++ supports non-virtual plural inheritance and that a variable can have same name as a type, this strips chances of referencing wrong object. It's necessary for template metaprogramming.

Another example would be &B::foo vs &B.foo in context of class B.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
2

Let extend @Deduplicator example:

#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.
}

Live on Coliru Viewer

Not having a possibility to differentiate with help of ::, which member we want to access, it is impossible to access members declared in a parent class with identical names.

273K
  • 29,503
  • 10
  • 41
  • 64
  • `A A` (variable name that is also a type name) isn't valid in C++ though, so this example doesn't work for now – Jimmy R.T. Feb 14 '20 at 10:41
  • 1
    @JimmyR.T. There is the working life example on Coliru Viewer. Confirm your statement please with a paragraph from the standard. – 273K Feb 14 '20 at 15:51
  • if one would add the cursed inheritance diamond here with same thing on other side, it would be a pinnacle of naming schizophrenia possible in C++ – Swift - Friday Pie Feb 15 '20 at 09:08