'::'を 'に置き換えます。'C ++で曖昧さを作成しますか?


95

C ++では、演算子::を使用して、名前空間またはクラスのクラス、関数、および変数にアクセスします。

オブジェクトのインスタンス変数/メソッドにアクセスするときのように、言語仕様がこれらのケースの.代わりに使用された場合、::それにより、::

C ++では型名でもある変数名が許可されていないので、それが起こる可能性があるケースは考えられません。

明確化:::選ばれた理由を尋ね.ているのではありません。


コメントは詳細な議論のためのものではありません。この会話はチャットに移動さました
サミュエルLiew

回答:


124

C ++を既存のCコード(オブジェクト名と構造体タグ間の名前の衝突を可能にする)とほぼ互換にする試みのため、C ++はクラス名とオブジェクト名の間の名前の衝突を許可します。

つまり:

struct data {
    static int member;
};

struct data2 {
    int member;
};

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

正当なコードです。


11
タイトルの質問に対する答えは「はい、そうでしょう」です。
エンリコマリアデアンジェリス

2
@EnricoMariaDeAngelisそれはそれほど単純ではありません。C ++がJavaやC#のような完全に新しい言語として開発されていた場合、あいまいさはおそらく回避できます。しかし、C ++は「クラス付きC」として開発されたので、そうではありません。「はい、それ」正しい答えですが、別の質問に対するものです。
キット。

待ち、割り当てラインがちょうど置くことを示していない.か、::(異なる効果を有する同じ2つの「単語」との間data.memberを指すmemberdataクラスのオブジェクトdata2に対し、data::member指すmemberクラスのdata)?
エンリコマリアデアンジェリス

1
はい、しかしそれは言語デザイナーが誇るべきものではありません。これは、互換性に関する決定の成果物にすぎません。
キット。

わかりました、今日のC ++の状況とこれまでのC ++の状況は(また)、C ++がC ++から開発された当時のCの内容に依存していることを理解しています。しかし、C ++についてはそのまま、なぜそうであるのかはさておき、すべて::をに変更するとあいまいになり.ます。ある意味、あなたはすでにイエスと答えました。私はあなたの最初のコメントに違反することはできません。たぶん私のレベルでは、そのコメントがスモーキーに見えるかもしれません。
エンリコマリアデアンジェリス

37

両方が有効であるが、異なるオブジェクトを参照している例:

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

コリルのライブをご覧ください。


そして、これは異なる設計上の決定で簡単に解決できませんでした
user253751

7

名前空間として使用されることと、名前空間またはタイプ名であることを意味する場所a::ba.b場所には違いがあります。C ++が非仮想複数継承をサポートし、変数が型と同じ名前を持つことができる場合、これにより、誤ったオブジェクトを参照する可能性がなくなります。テンプレートのメタプログラミングに必要です。::a

別の例は、クラスBのコンテキストでの&B::foovs &B.fooです。


2

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

Coliru Viewerでライブ

::の助けを借りて区別する可能性がないため、どのメンバーにアクセスしたいか、同じ名前の親クラスで宣言されたメンバーにアクセスすることは不可能です。


A A(型名でもある変数名)はC ++では無効なので、この例は今のところ機能しません
Jimmy RT

1
@ JimmyR.T。Coliru Viewerには実例があります。規格の段落で声明を確認してください。
SM

呪われた継承のひし形を反対側にも同じように追加すると、C ++で統合失調症に名前を付けることができるという頂点になります
Swift-Friday Pie
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.