回答:
C ++を既存のCコード(オブジェクト名と構造体タグ間の名前の衝突を可能にする)とほぼ互換にする試みのため、C ++はクラス名とオブジェクト名の間の名前の衝突を許可します。
つまり:
struct data {
static int member;
};
struct data2 {
int member;
};
void f(data2& data) {
data.member = data::member;
}
正当なコードです。
.
か、::
(異なる効果を有する同じ2つの「単語」との間data.member
を指すmember
のdata
クラスのオブジェクトdata2
に対し、data::member
指すmember
クラスのdata
)?
::
をに変更するとあいまいになり.
ます。ある意味、あなたはすでにイエスと答えました。私はあなたの最初のコメントに違反することはできません。たぶん私のレベルでは、そのコメントがスモーキーに見えるかもしれません。
両方が有効であるが、異なるオブジェクトを参照している例:
#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';
}
コリルのライブをご覧ください。
名前空間として使用されることと、名前空間またはタイプ名であることを意味する場所a::b
とa.b
場所には違いがあります。C ++が非仮想複数継承をサポートし、変数が型と同じ名前を持つことができる場合、これにより、誤ったオブジェクトを参照する可能性がなくなります。テンプレートのメタプログラミングに必要です。::
a
別の例は、クラスBのコンテキストでの&B::foo
vs &B.foo
です。
@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.
}
::の助けを借りて区別する可能性がないため、どのメンバーにアクセスしたいか、同じ名前の親クラスで宣言されたメンバーにアクセスすることは不可能です。
A A
(型名でもある変数名)はC ++では無効なので、この例は今のところ機能しません