web-dev-qa-db-ja.com

内部クラスを前方宣言するにはどうすればよいですか?

可能性のある複製:
C++のネストされた型/クラスの前方宣言

私はそのようなクラスを持っています...

class Container {
public:
    class Iterator {
        ...
    };

    ...
};

他の場所では、参照によってContainer :: Iteratorを渡したいのですが、ヘッダーファイルを含めたくありません。クラスを前方宣言しようとすると、コンパイルエラーが発生します。

class Container::Iterator;

class Foo {
    void Read(Container::Iterator& it);
};

上記のコードをコンパイルすると...

test.h:3: error: ‘Iterator’ in class ‘Container’ does not name a type
test.h:5: error: variable or field ‘Foo’ declared void
test.h:5: error: incomplete type ‘Container’ used in nested name specifier
test.h:5: error: ‘it’ was not declared in this scope

Iteratorクラスを宣言するヘッダーファイルを含める必要がないように、このクラスを前方宣言するにはどうすればよいですか?

143
bradtgmurray

これは単に不可能です。コンテナの外部でネストされた構造を前方宣言することはできません。コンテナ内でのみ前方宣言できます。

次のいずれかを行う必要があります

  • クラスをネストしないようにする
  • ネストされたクラスが最初に完全に定義されるように、宣言の順序を変更します
  • 関数で使用でき、ネストされたクラスで実装できる共通の基本クラスを作成します。
125
JaredPar

不完全なクラスでの内部クラスの前方宣言が機能するとは思わない(クラス定義がないため、実際にis内部クラスがあるかどうかを知る方法がないため)。したがって、内部クラスを前方宣言したコンテナの定義を含める必要があります。

class Container {
public:
    class Iterator;
};

次に、別のヘッダーにContainer :: Iterator:を実装します。

class Container::Iterator {
};

次に、コンテナヘッダーのみを#includeします(または、前方宣言を心配せず、両方を含めるだけです)

23
Todd Gardner

私はあなたが望むものを正確に行う方法を知っていませんが、テンプレートを使用する意思がある場合は、回避策があります:

// Foo.h  
struct Foo
{
   export template<class T> void Read(T it);
};

// Foo.cpp
#include "Foo.h"
#include "Container.h"
/*
struct Container
{
    struct Inner { };
};
*/
export template<> 
  void Foo::Read<Container::Inner>(Container::Inner& it)
{

}

#include "Foo.h"
int main()
{
  Foo f;
  Container::Inner i;
  f.Read(i);  // ok
  f.Read(3);  // error
}

うまくいけば、このイディオムがあなたにとって役に立つかもしれません(そして、あなたのコンパイラがEDGベースで、エクスポートを実装することを願っています;))。

1
Faisal Vali