40

(私は、スコープ解決演算子が何をするか、いつどのように使用するかを知っています。)

この目的で演算子を::使用する代わりに、C++ に演算子があるのはなぜですか? .Java には個別の演算子がなく、正常に動作します。C++ と Java の間には、解析可能にするために C++ が別の演算子を必要とすることを意味する違いはありますか?

私の唯一の推測は::、優先順位の理由で必要であるということですが、たとえば、.. 私が考えることができる唯一の状況は、

a.b::c;

として解析されます

a.(b::c);

、しかし、とにかくこのような構文が合法になる状況は考えられません。

「やってることが違うから、見た目も違う」ということなのかもしれません。::しかし、それはが よりも優先される理由を説明していません.

4

7 に答える 7

34

C++ 標準委員会の誰かが、このコードを機能させるのは良い考えだと考えたからです。

struct foo
{
  int blah;
};

struct thingy
{
  int data;
};

struct bar : public foo
{
  thingy foo;
};

int main()
{
  bar test;
  test.foo.data = 5;
  test.foo::blah = 10;
  return 0;
}

基本的に、メンバー変数と派生クラスの型に同じ名前を付けることができます。これが重要だと思っていたときに、誰かが何を吸っていたのか、私にはわかりません。しかし、そこにあります。

コンパイラがを参照.すると、左にあるものがオブジェクトであることがわかります。が表示された場合::、それは型名または名前空間でなければなりません (または何もない、グローバル名前空間を示します)。それがこの曖昧さを解決する方法です。

于 2012-02-18T03:52:32.350 に答える
30

.C ++が使用する場所を使用しない::理由は、これが言語の定義方法であるためです。::aもっともらしい理由の1つは、以下に示す構文を使用してグローバル名前空間を参照することです。

int a = 10;
namespace M
{
    int a = 20;
    namespace N
    {
           int a = 30;
           void f()
           {
              int x = a; //a refers to the name inside N, same as M::N::a
              int y = M::a; //M::a refers to the name inside M
              int z = ::a; //::a refers to the name in the global namespace

              std::cout<< x <<","<< y <<","<< z <<std::endl; //30,20,10
           }
    }
}

オンラインデモ

Javaがこれをどのように解決するのかわかりません。Javaにグローバル名前空間があるかどうかさえわかりません。C#では、構文を使用してグローバル名を参照しますglobal::a。これは、C#にも::演算子があることを意味します。


しかし、とにかくこのような構文が合法であるような状況は考えられません。

a.b::cのような構文は合法ではないと誰が言いましたか?

次のクラスを検討してください。

struct A
{
    void f() { std::cout << "A::f()" << std::endl; }
};

struct B : A
{
    void f(int) { std::cout << "B::f(int)" << std::endl; }
};

今これを見てください(ideone):

B b;
b.f(10); //ok
b.f();   //error - as the function is hidden

b.f()関数が非表示になっているため、そのように呼び出すことはできません。GCCは次のエラーメッセージを表示します。

error: no matching function for call to ‘B::f()’

を呼び出すb.f()(またはむしろA::f())には、スコープ解決演算子が必要です。

b.A::f(); //ok - explicitly selecting the hidden function using scope resolution

ideoneでのデモ

于 2012-02-18T03:38:32.820 に答える
10

C++ に :: 演算子があるのはなぜですか。この目的のためのオペレーター?

その理由は、Stroustrup 自身によって次のように述べられています。

C with Classes では、特定のオブジェクトのメンバーの選択を表すだけでなく、クラスのメンバーシップを表すためにドットが使用されました。

これはいくつかの小さな混乱の原因であり、あいまいな例を作成するために使用することもできました. これを軽減するために::、クラスのメンバーシップを意味するように導入され.、オブジェクトのメンバーシップ専用に保持されました

(Bjarne Stroustrup A History of C++: 1979-1991 page 21 - § 3.3.1)

さらに、それは本当です

彼らは異なることをしているので、見た目も違うかもしれません

確かに

N::mどちらの式にも値はありませNん。およびは、コンパイラに認識される名前であり、式の評価ではなく (コンパイル時の) スコープ解決を実行します。x が名前空間やクラスではなくオブジェクトである x::y のオーバーロードを許可することを想像できますが、最初の外観とは異なり、新しい構文を導入する必要があります (を許可するため)。このような合併症がもたらす利点は明らかではありません。mNm::expr::expr

演算子.(ドット) は、原則として、 に使用されるのと同じ手法を使用してオーバーロードでき->ます。

(Bjarne Stroustrup のC++ スタイルとテクニックに関する FAQ )

于 2016-04-09T15:40:16.620 に答える
9

Javaとは異なり、C++には多重継承があります。これは、あなたが話している種類のスコープ解決が重要になる1つの例です。

#include <iostream>
using namespace std;
struct a
{
    int x;
};
struct b
{
    int x;
};
struct c : public a, public b
{
    ::a a;
    ::b b;
};
int main() {
    c v;
    v.a::x = 5;
    v.a.x = 55;
    v.b::x = 6;
    v.b.x = 66;
    cout << v.a::x << " " << v.b::x << endl;
    cout << v.a.x << " " << v.b.x << endl;
    return 0;
}
于 2012-02-18T03:39:22.823 に答える
3

コードを読みやすくするために、C++ dot/:: の使用はスタイルの選択であると常に想定していました。OPが書いているように、「彼らは違うことをするので、違うように見えるはずです.」

ずっと前に C++ から C# に移行したとき、ドットだけを使用すると混乱することがわかりました。私は を見てA::doStuff(); B.doStuff();、1 つ目は名前空間内の通常の関数であり、2 つ目はインスタンス B のメンバー関数であることを知っていました。

C++ は、おそらく Basic、アセンブリ、Pascal、Fortran に続く、私の 5 番目の言語です。したがって、これが第一言語シンドロームではないと思います。今では、C# プログラマーになっています。ただし、私見ですが、両方を使用したことがある場合は、名前空間に C++ スタイルのダブルコロンを使用した方が読みやすくなります。Java/C# は、学習曲線の最前線を (うまく) 緩和するために、両方にドットを選択したように感じます。

于 2013-12-29T19:05:26.430 に答える
3

演算子の優先順位に関する質問の最後の部分に答えるために:

class A {
public:
  char A;
};

class B : public A {
public:
  double A;
};

int main(int c, char** v)
{
  B myB;
  myB.A = 7.89;
  myB.A::A = 'a';
  // On the line above a hypothetical myB.A.A
  // syntax would parse as (myB.A).A and since
  // (myB.A) is of type double you get (double).A in the
  // next step. Of course the '.' operator has no
  // meaning for doubles so it causes a syntax error. 
  // For this reason a different operator that binds
  // more strongly than '.' is needed.
  return 0;
}
于 2012-02-18T04:20:28.903 に答える
1

スコープ解決演算子 (::) は、クラス外の関数を定義する場合、またはグローバル変数を使用したいが同じ名前のローカル変数もある場合に使用されます。

于 2015-03-02T17:04:29.587 に答える