0
struct X;

struct Y {
  void f(X*);
};

struct X { //definition
private:
  int i;
public:
  friend void Y::f(X*);
  <SNIP'd>
};

「構造体には、型のオブジェクトを変更するYメンバー関数があります。C++コンパイラでは、参照する前にすべてを宣言する必要があるため、これは少し難問です。したがって、構造体は、そのメンバーをとして宣言する前に宣言する必要があります。構造体の友人。しかし、宣言されるためには、構造体が最初に宣言されなければなりません!f()XYY::f(X*)XY::f(X*)X

これが解決策です。オブジェクトY::f(X*)のアドレスを取ることに注意してください。コンパイラは、型のサイズに関する完全な情報がなくても、渡されるオブジェクトに関係なく、固定サイズのアドレスを渡す方法を常に知っているXため、これは重要です。」

だからここにあります:

struct X; struct Y { ... }; struct X { ... };

私の質問はこれです:

  1. Xコンパイラが、不完全に宣言されていると主張するのはなぜstruct X;ですか?

    結局のところ、作者が指摘しているように、「コンパイラは、固定サイズのアドレスを渡す方法を常に知っています」。これは、コンパイラーにX構造体であり、すぐに続くことを通知する宣言にすぎません。そのため、コンパイラーが次の文字を入力するように強く主張しているのはなぜですかX。結局、私はXそれ自体を使用していませんか?その時点で生成されているアセンブリ言語コードはありません。X*そしてそれが確かに読むとき、それはそれがアドレス(ポインタ)であると言うことができます。なぜ:struct X;必要ですか?

    関数を宣言することの全体的なポイントは、実際に使用する前に型をチェックすることです。だから私がそうするなら:

     int foo(void); foo(30); 
    

    コンパイラは遠吠えします。しかし、上記で、私が言わなければ、それはstruct X;どのような違いを生むのでしょうか?X彼は私の(関数名)のスペルをチェックしているだけですか?

  2. 構造体YとXの配置を逆にしないのはなぜですか?そのように:
    struct Y; struct X { ... }; struct Y { ... };
    私は得る:

    エラー:不完全なタイプの無効な使用'struct main()::Y'

    Y明らかに、コンパイラは( )の不完全な型指定に満足していません struct Y;。しかし、どのような貴重な情報が欠けていますか?結局のところstruct Y; すぐに続くコンパイラーに通知する必要がありYます(Q1で行っていたのと同じですstruct X; struct Y {}; struct X{};) 。

  3. なぜ作者は構造体Xを定義として参照するのですか?私がそうする場合: struct X { ... };これは確かに宣言ですか?そして、私がそのように構造をインスタンス化するとき:Xfoo; それならそれは定義ですか?正しい?

  4. これを行うにはどうすればよいですか:

    struct X {
      friend void Y::f(X*);
      void f(Y*);
    };
    
    struct Y {
      friend void X::f(Y*);
      void f(X*);
    };
    
4

2 に答える 2

2

コンパイラがXを次のように不完全に宣言するように要求するのはなぜですか:struct X ?? 結局のところ、作者が指摘しているように、「コンパイラは、固定サイズのアドレスを渡す方法を常に知っています。」

あなたはしません:これも機能します:

struct Y { void f(struct X*); };

class X {
    int i;
    friend void Y::f(X*);
};

他に何を提案しますか?

また、実際にメソッドを定義しない限り、値を渡すときに完全な型を持っている必要はありません。

struct Y { void f(struct X); };

// too early:    
void Y::f(struct X) { /* whoops compile error */ }

class X {
    int i;
    friend void Y::f(X);
};

// ok here:
void Y::f(X) { /* compile success */ }
于 2012-06-22T10:55:18.710 に答える
1

結局のところ、著者が指摘しているように、「コンパイラは固定サイズのアドレスを渡す方法を常に知っている..」これは、コンパイラに X が構造体であり、すぐに続くことを伝える宣言にすぎません。文字を入力するほどしつこい:struct X;結局のところ、私は X 自体を使用していないのですか?? その時点で生成されるアセンブリ言語コードはありません..そして、「X*」を読み取ると、それがアドレス(ポインタ)であることが確実にわかります..なぜ:struct X;が必要なのですか??

著者は厄介な詳細をすべて伝えているわけではありません。コンパイラーは、オブジェクトの種類がわかっている場合、ポインター (アドレス) を渡す方法を知っていますX。この言語charでは、ワード アドレス指定可能なマシン上のポインターや関数へのポインターなど、一部のポインターを異なるサイズにすることができます。

したがって、組み込み型の関数または typedef ではなく、コンパイラに通知する必要がありますXstruct

于 2012-06-22T11:12:43.283 に答える