2

記事で次のコードに出くわしました

struct entire_program   
{
    struct B;

    struct A
    {
        B *bbb;
        void Aa() { B bb; bb.Bb(); };
    };

    struct B
    {
        A aaa;
        void Bb() { A aa; aa.Aa(); };
    };
};

Bb()この場合、メソッドを呼び出すことが許可されているのに、メソッドに変更struct entire_programするnamespace entire_programとコンパイラ エラーが発生するのはなぜですか?

私はすでにこの質問を読んでいます。私が求めているのは、クラス/構造体/共用体内でまだ定義されていないメソッドを呼び出すことができる場合、名前空間が同じように機能しないのはなぜですか? この行動の背後にある動機に興味があります。

Programmers.SE に関する関連する質問(記事で紹介されているコーディング スタイルに関心のある方向け)

4

2 に答える 2

2

これは、C++でクラスと名前空間が機能する方法です。クラスは、(クラスメンバーの)名前のセット全体を候補として持ってくる必要があります。そうしないと、クラスメンバーを注文するのに大きな負担がかかり、たとえば、パブリックインターフェイスを最初に注文できない場合があります。

一方、名前空間はC関数とほぼ同じように機能し、ソースファイルにリストされている順序で順番に処理されます。名前空間/グローバルスコープで呼び出す前にいつでも関数を宣言できるため、特別な機能は必要ありません。

于 2012-12-21T00:44:54.183 に答える
1

クラスと名前空間の両方で循環依存が可能です。循環依存の状況で物事を正しく定義するだけの問題です。

あなたの場合、クラス内のメンバー関数定義が特別に扱われているためにコンパイルされたコードstruct entire_program:現在のポイントの上と下の両方で、囲んでいるクラスの定義全体を「見る」ことができます。ただし、囲んでいる名前空間の定義全体を確認することはできません。名前空間を使用すると、コンパイラは現在のポイントより上で宣言されたものだけを確認します。

クラスと名前空間は非常に異なるものであるため、通常、2つを自由に切り替える問題は実際には発生しません。しかし、説明のためだけに、これは多くの場合、あなたの人工的な例を含めて達成することができます

namespace entire_program   
{
    struct B;

    struct A
    {
        B *bbb;
        void Aa();
    };

    struct B
    {
        A aaa;
        void Bb() { A aa; aa.Aa(); }
    };
}

inline void entire_program::A::Aa()
{
  B bb; bb.Bb();
}   

上記の私の実装はあなたの実装と同じ効果がありますが、メンバー関数の特別な扱いに依存していません。struct entire_program必要に応じて、とを自由に切り替えることができnamespace entire_programます。;名前空間の定義には、終了後にがないことを覚えておいてください}

于 2012-12-21T00:47:35.253 に答える