1

このコードは特別なことは何もしません。前方宣言の問題を示すのはほんの一部です。簡単な質問: なぜ機能しないのですか? また、強制的に機能させるにはどうすればよいですか?

class A;

class B {
    A obj;
public:
    int getB() const {
        return 0;
    }
    void doSmth() {
        int a = obj.getA();
    }
};

class A {
    B obj;
public:
    int getA() const {
        return 1;
    }
    void doSomething() {
        int b = obj.getB();
    }
};

このコードは私にエラーを与えます:

error C2079: 'B::obj' uses undefined class 'A'
error C2228: left of '.getA' must have class/struct/union
4

4 に答える 4

6

前方宣言では、オブジェクトへのポインターと参照のみを使用できます。クラス定義が利用可能になる前に、完全に定義しようとしています。

これを機能させるには、Aのobjをポインターに変更するか(おそらく最良の解決策ではない)、PIMPLイディオム(google it)を使用する必要があります。これにより、これを回避できます。

于 2012-08-10T17:39:43.630 に答える
4

あなたの構造は単に意味がありません。サブオブジェクトの無限再帰シーケンスが含まれているため、適切に定義された構造体でもAありません。B

これと同じ問題をもう少し難読化した例を示しました。

struct Box { Box hubert; };

繰り返しますが、このデータ構造には意味がありません。

プログラミングのすべては、そうするなら、有限で十分に根拠のあるものでなければなりません。


実際には、C++ は、完全な型を持つメンバー オブジェクトのみをクラス定義に含める必要があることを要求することで、ユーザーがしようとしていることを禁止します。しかし、それは論理的な意味を成すことに要約されます。このようなデータ構造をどのように初期化するかを考えてみてください。常に何かが最初に来なければなりません。

于 2012-08-10T17:40:53.737 に答える
3

このタイプの循環依存は、C++では不可能です。お互いを含むオブジェクトを持つことはできません。ただし、ポインタまたは参照を格納することはできます。また、完全な定義がないと、クラスのメソッドを実際に使用することはできません。

したがって、実行する必要がある2つのことがあります。

1)オブジェクトをポインタに置き換えます。

2)クラス定義の後にメソッドを実装します。inlineこれらがヘッダーにある場合は、複数の定義を防ぐためにマークを付ける必要があります。

class A;
class B {
    std::shared_ptr<A> obj;
public:
    int getB() const;
    void doSmth();
};

class A {
    std::shared_ptr<B> obj;
public:
    int getA() const;
    void doSomething();
};


inline int B::getB() const {
        return 0;
    }
inline void B::doSmth() {
        int a = obj->getA();
    }


inline int A::getA() const {
        return 1;
    }
inline void A::doSomething() {
        int b = obj->getB();
    }
于 2012-08-10T17:39:51.017 に答える
1

問題を解決するには、obj A と obj B のヘッダー ファイルを作成する必要があると思います。B が定義されると、A が持つ関数/メソッドではなく、A が存在することだけがわかります。

各ヘッダー ファイルには、各関数/メソッドのプロトタイプを含める必要があります。例:

class A{
   int GetA() const;
   void DoSomething();
}

フォーマットがずれている可能性があります (私は Obj C ヘッダーに慣れています) が、それは役立つはずです。

于 2012-08-10T17:47:58.080 に答える