6
void foo()
{
    bar();          // error: ‘bar’ has not been declared
}

void bar()
{
}

namespace N
{
    void foo()
    {
        N::bar();   // error: ‘bar’ is not a member of ‘N’
    }

    void bar()
    {
    }
}

class C
{
    static void foo()
    {
        C::bar();   // works just fine
    }

    static void bar()
    {
    }
};

宣言を超えて関数呼び出しを処理するこの矛盾の背後にある理論的根拠は何ですか? 名前空間やグローバル スコープではなく、クラス内で実行できるのはなぜですか?

4

5 に答える 5

3

メンバー関数は、クラス内、クラス宣言の後、またはそれぞれの一部で定義できます。

ここで一貫性を保つために、関数がインラインで定義されているクラスのルールは、関数がクラスのに定義されているかのようにコンパイルする必要があるということです。

あなたのコード

class C {
     static void foo()
     {
         C::bar();   // works just fine 
     }

     static void bar()
     {     }
 }; 

と同じようにコンパイルします

class C {
     static void foo();
     static void bar();
 }; 

 void C::foo()
 {  C::bar();  }

 void C::bar()
 {     }

関数はすべて、クラスで宣言されたすべてのものを見ることができるため、可視性に魔法はありません。

于 2012-08-06T10:59:41.280 に答える
1
  1. 名前空間を再度開いたり、新しいものをどこにでも追加したりできます。クラスを再開することはできません。すべてのコンテンツを1か所に配置する必要があります。

  2. 関数プロトタイプは名前空間では有効ですが、クラスでは有効ではありません。

あなたは書ける

namespace n
{
    void foo();

    void bar()
    {
        foo();
    }

    void foo()
    {
    }
}

だがしかし

class C
{
    void foo();

    void bar()
    {
        foo();
    }

    void foo()
    {
    }
}

したがって、クラスにはそのような機能がはるかに必要であり、名前空間よりもクラスに実装する方がはるかに簡単です。

于 2012-08-06T10:13:27.420 に答える
0

確かではありませんが、私の考えでは、 aclassは、すべての内部コンポーネントが連携して (一般的に言えば) 動作するオブジェクト(不適切に使用されている) であり、そのメンバーは間違いなくそのメソッドを必要とします。

しかし、名前空間は異なり、機能は関係ありません。これは、関数が名前空間内の他のすべての関数と連携することを意図していないことを意味します。

したがって、宣言と定義を分割することが最善の方法です。

同じ宣言ファイルにある可能性が最も高く、そのように機能するfoo()必要がある場合bar()

于 2012-08-06T09:57:57.470 に答える
0

おそらく、クラス宣言が 1 か所にあり、コンパイラがそのメンバーの情報を簡単に取得できるためです。

一方、名前空間は、大量のさまざまなファイルに含まれている可能性があり、そもそもどこを調べればよいかわからないため、コンパイラがそれらを調べることは期待できません。

これを避けるには、関数プロトタイプを使用してください。

于 2012-08-06T09:52:26.830 に答える
0

以下の標準からの引用を参照してください

3.3.7 クラススコープ [basic.scope.class]

1) 次の規則は、クラスで宣言された名前の範囲を示しています。1) クラスで宣言された名前の潜在的なスコープは、名前の宣言ポイントに続く宣言領域だけでなく、その中のすべての関数本体、デフォルト引数、および非静的データメンバーのブレースまたはイコイニシャライザーからも構成されます。クラス(ネストされたクラスのそのようなものを含む)。

2) クラス S で使用される名前 N は、そのコンテキスト内で同じ宣言を参照し、S の完全なスコープで再評価される場合に参照するものとします。この規則違反の診断は必要ありません。

typedef int c;
enum { i = 1 };

class X {
     char v[i]; // error: i refers to ::i
                // but when reevaluated is X::i
     int f() { return sizeof(c); } // OK: X::c
     char c;
     enum { i = 2 };
};
于 2012-08-06T11:01:50.733 に答える