struct X;
struct Y {
void f(X*);
};
struct X { //definition
private:
int i;
public:
friend void Y::f(X*);
<SNIP'd>
};
「構造体には、型のオブジェクトを変更する
Y
メンバー関数があります。C++コンパイラでは、参照する前にすべてを宣言する必要があるため、これは少し難問です。したがって、構造体は、そのメンバーをとして宣言する前に宣言する必要があります。構造体の友人。しかし、宣言されるためには、構造体が最初に宣言されなければなりません!f()
X
Y
Y::f(X*)
X
Y::f(X*)
X
これが解決策です。オブジェクト
Y::f(X*)
のアドレスを取ることに注意してください。コンパイラは、型のサイズに関する完全な情報がなくても、渡されるオブジェクトに関係なく、固定サイズのアドレスを渡す方法を常に知っているX
ため、これは重要です。」
だからここにあります:
struct X; struct Y { ... }; struct X { ... };
私の質問はこれです:
X
コンパイラが、不完全に宣言されていると主張するのはなぜstruct X;
ですか?結局のところ、作者が指摘しているように、「コンパイラは、固定サイズのアドレスを渡す方法を常に知っています」。これは、コンパイラーに
X
構造体であり、すぐに続くことを通知する宣言にすぎません。そのため、コンパイラーが次の文字を入力するように強く主張しているのはなぜですかX
。結局、私はX
それ自体を使用していませんか?その時点で生成されているアセンブリ言語コードはありません。X*
そしてそれが確かに読むとき、それはそれがアドレス(ポインタ)であると言うことができます。なぜ:struct X;
必要ですか?関数を宣言することの全体的なポイントは、実際に使用する前に型をチェックすることです。だから私がそうするなら:
int foo(void); foo(30);
コンパイラは遠吠えします。しかし、上記で、私が言わなければ、それは
struct X;
どのような違いを生むのでしょうか?X
彼は私の(関数名)のスペルをチェックしているだけですか?構造体YとXの配置を逆にしないのはなぜですか?そのように:
struct Y; struct X { ... }; struct Y { ... };
私は得る:エラー:不完全なタイプの無効な使用
'struct main()::Y'
Y
明らかに、コンパイラは( )の不完全な型指定に満足していませんstruct Y;
。しかし、どのような貴重な情報が欠けていますか?結局のところstructY
; すぐに続くコンパイラーに通知する必要がありY
ます(Q1で行っていたのと同じですstruct X; struct Y {}; struct X{};
) 。なぜ作者は構造体
X
を定義として参照するのですか?私がそうする場合:struct X { ... };
これは確かに宣言ですか?そして、私がそのように構造をインスタンス化するとき:X
foo; それならそれは定義ですか?正しい?これを行うにはどうすればよいですか:
struct X { friend void Y::f(X*); void f(Y*); }; struct Y { friend void X::f(Y*); void f(X*); };