3

ヘッダーを含める順序が重要な循環依存の問題に遭遇しました。この問題は似ていますが、一方のクラスがもう一方のオブジェクトをインスタンス化するソリューションについては説明していません。

問題:

  • 私には2つのクラスがあります:FooとBarです。バーはテンプレート化されています。(Fooはテンプレート化されている場合とされていない場合があります)。
  • FooにはBarのインスタンスがあり、BarにはタイプFooのポインターがあり、Barの実装はこのポインターを介してFooのメンバーにアクセスする必要があります。
  • FooとBarは 別々のファイル内に実装する必要があります。Barはテンプレート化されているため、その宣言と実装は同じファイルに含まれている必要があります。

次のコードでは、main.cppにFoo.hの前にBar.hが含まれている場合、コードはコンパイルされますが、Foo.hがBar.hの前に含まれている場合はコンパイルされません。main.cppにヘッダーが含まれている順序に関係なく、コードをコンパイルする方法はありますか?

Foo.h

#ifndef FOO_H
#define FOO_H

#include"Bar.h"
class Foo
{
    public:
        Bar<> B;
        void fooStuff(){};

};
#endif

Bar.h

#ifndef BAR_H
#define BAR_H

class Foo;
template<int N=0> class Bar
{
    public:
        Foo * F;
        void barStuff();
};

#include"Foo.h"
 template<int N> void Bar<N>::barStuff()
{
        F->fooStuff();
};
#endif

main.cpp

#include"Foo.h"
#include"Bar.h"
int main()
{
    Foo F;
    F.B.barStuff();
};
4

2 に答える 2

4

はい:完全な定義を必要としないポインタのみを使用するため、Foo前に宣言します。次に、後に定義します-オブジェクトを使用するため、定義が必要です。BarBarFooBar

class Foo;

template<int N> class Bar
{
    public:
        Foo * M;
        void barStuff();
};

class Foo
{
    public:
        Bar<42> B;
        void fooStuff(){}
};

template<int N> void Bar<N>::barStuff()
{
    M->fooStuff();
}

一般に、サイズやメンバーなど、クラスのプロパティを必要とするものには完全な定義が必要であり、関数、ポインター、または参照を宣言するときにクラス名を使用するための宣言のみが必要です。

于 2012-07-09T11:26:09.673 に答える
2

main.cppに含まれる順序に関係なく、Fooの前にBarを含める必要があります。次のハックは機能しているようです。

Foo.hで、ヘッダーガードの外側にBar.hを含めます。Barにはヘッダーガードもあるため、複数回含まれることはありません。

Foo.h

#include"Bar.h"

#ifndef FOO_H
#define FOO_H


class Foo
{
    public:
        Bar<> B;
        void fooStuff(){};

};
#endif

Bar.h

#ifndef BAR_H
#define BAR_H

class Foo;
template<int N=0> class Bar
{
    public:
        Foo * F;
        void barStuff();
};

#include"Foo.h"
 template<int N> void Bar<N>::barStuff()
{
        F->fooStuff();
};
#endif

main.cpp

#include"Foo.h"
#include"Bar.h"
int main()
{
    Foo F;
    F.B.barStuff();
};
于 2012-07-10T06:50:15.093 に答える