C ++のネストされたクラスの前方宣言エラー
-
10-07-2019 - |
質問
クラスA内でクラスBを宣言して使用しようとしています
Aの外でBを定義します。
Bjarne Stroustrup
彼の本「The C ++ programming language」でこれを使用しています
(たとえば、StringクラスとSrepクラスなど、293ページ)。
つまり、これは問題を引き起こす最小限のコードです
class A{
struct B; // forward declaration
B* c;
A() { c->i; }
};
struct A::B {
/*
* we define struct B like this becuase it
* was first declared in the namespace A
*/
int i;
};
int main() {
}
このコードでは、g ++で次のコンパイルエラーが発生します。
tst.cpp: In constructor ‘A::A()’:
tst.cpp:5: error: invalid use of undefined type ‘struct A::B’
tst.cpp:3: error: forward declaration of ‘struct A::B’
C ++のよくある質問を見てみましたが、得られたクローズセットはこちらおよびこちらが、
それらは私の状況には当てはまりません。
また、ここからこれを読むが、問題を解決していません。
gccとMSVC 2005の両方で、これに関するコンパイラエラーが発生します
解決
構造Bの定義後にAのコンストラクターを定義します。
他のヒント
式 c-> i
は、 struct A :: B
へのポインターを逆参照するため、プログラムのこの時点で完全な定義が表示される必要があります。
最も簡単な修正方法は、 A
のコンストラクタを非インラインにし、 struct A :: B
の定義後にそのボディを提供することです。
これは、定義を宣言とは別にしたい理由の良い例です。コンストラクター A :: A()
が struct A :: B
の定義の後に定義されるように、物事の順序を変更する必要があります。
class A
{
struct B;
B* c;
A();
};
struct A::B
{
int i;
};
A::A() { c->i; }
int main()
{
return 0;
}
興味深いことに、Stroustrupの本で言及されている293ページ(「11.12 A String Class」)で同じ問題にぶつかりました。
印刷された本で提供されている例は、struct Srepの定義後にそれらを定義するのではなく、インラインとして以下のメソッドを提供しているように思われます
class String {
// ...
void check(int i) const { if (i<0 || rep->sz <=i) throw Range(); }
char read(int i) const { return rep->s[i]; }
void write(int i, char c) { rep=rep->get_own_copy(); rep->s[i]=c; }
...etc...
少しグーグルで調べたところ、このString Classの著者の最新の実装が見つかりました。 http://www2.research.att.com/~bs/string_example.c
彼は、このスレッドで言及されている問題を回避するために、これらのメソッドがインラインでなくなるように修正したようです。