13

なぜ C++ の使用前宣言規則がクラス内で成立しないのか疑問に思っています。

この例を見てください:

#ifdef BASE
struct Base {
#endif
    struct B;
    struct A {
        B *b;
        A(){ b->foo(); }
    };

    struct B {
        void foo() {}
    };
#ifdef BASE
};
#endif

int main( ) { return 0; }

BASE が定義されている場合、コードは有効です。

A のコンストラクター内で、まだ宣言されていない B::foo を使用できます。

なぜこれが機能するのですか?また、ほとんどの場合、クラス内でのみ機能するのはなぜですか?

4

4 に答える 4

8

これは、関数定義がインラインで記述されている場合でも、メンバー関数はクラス定義全体がコンパイラによって解析された後にのみコンパイルされるのに対し、通常の関数は読み取られた直後にコンパイルされるためです。C++ 標準では、この動作が必要です。

于 2010-10-30T20:17:09.250 に答える
8

よく言えば、C++ には「declare before use ルール」はありません。かなり複雑な名前検索の規則がありますが、多くの例外を除いて、一般的な「使用規則の前に宣言」に大まかに単純化できます (そしてしばしばそうです)。(ある意味では、状況は「演算子の優先順位と結合規則」に似ています。言語仕様にはそのような概念はありませんが、完全に正確ではありませんが、実際にはそれらを使用することがよくあります。)

これは実際にはそれらの例外の 1 つです。C++ のメンバー関数定義は、クラス定義のに定義されているかのように、これらのメンバーの本体からの名前検索が実行されるという意味で、その「使用規則の前に宣言」から明確かつ意図的に除外されています。

言語仕様は、3.4.1/8 (および脚注 30) でそれを述べていますが、別の表現を使用しています。メンバー関数定義からの名前検索中に、メンバー関数定義のの部分だけでなく、クラス定義全体が検査されると言われています。脚注 30 には、クラス定義の内部またはクラス定義の外部で定義された関数のルックアップ規則は同じであると述べられています (これは、上で述べたこととほとんど同じです)。

あなたの例は少し重要です。ネストされたクラスのメンバー関数の定義について、すぐに疑問が生じます。それらは、最も外側のクラスの定義の後に定義されているかのように解釈されるべきですか? 答えはイエスです。3.4.1/8 もこの状況をカバーしています。

「Design & Evolution of C++」という本では、これらの決定の背後にある理由が説明されています。

于 2010-10-30T20:24:50.847 に答える
3

これに関する標準の章と節がわかりません。

しかし、クラス内で厳密に「使用前に宣言する」ルールを適用すると、クラス宣言の最後でメンバー変数を宣言することもできなくなります。たとえば、コンストラクターの初期化リストでそれらを使用するには、最初にそれらを宣言する必要があります。

「使用前に宣言する」ルールがクラス宣言内で少し緩和され、「よりクリーンな」全体レイアウトが可能になったと想像できます。

私が言ったように、ただの推測です。

于 2010-10-30T20:16:18.090 に答える
1

C++ の定義における最も頑固な問題は、名前の検索に関するものです。名前のどの用途がどの宣言を参照しているのか? ここでは、ルックアップの問題の 1 種類だけを説明します。それは、クラス メンバー宣言間の順序の依存関係に関連するものです。[...]

目標間の矛盾のために困難が生じます。

  1. ソーステキストを一度だけ読み込んで構文解析を実行できるようにしたいと考えています。
  2. クラスのメンバーを並べ替えても、クラスの意味が変わるべきではありません。
  3. インラインで明示的に記述されたメンバー関数本体は、アウト オブ ラインで記述された場合と同じことを意味する必要があります。
  4. 外側のスコープからの名前は、内側のスコープから使用できる必要があります (C と同じ方法で)。
  5. 名前検索の規則は、名前が参照するものとは無関係でなければなりません。

これらすべてが当てはまる場合、言語の解析はかなり高速になり、ユーザーはこれらのルールについて心配する必要がなくなります。現在のルールは、この理想に非常に近づいています。

[The Design And Evolution Of C++、セクション 6.3.1 と呼ばれるルックアップの問題(138 ページ)]

于 2010-10-31T12:15:43.877 に答える