186

我有这样的课...

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 类的头文件?

4

3 回答 3

165

这根本不可能。您不能在容器外转发声明嵌套结构。您只能在容器内转发声明它。

您需要执行以下操作之一

  • 使类非嵌套
  • 更改您的声明顺序,以便首先完全定义嵌套类
  • 创建一个既可以在函数中使用又可以由嵌套类实现的通用基类。
于 2009-06-20T15:07:15.040 回答
26

我不相信在不完整的类上向前声明内部类(因为没有类定义,就无法知道是否真的存在内部类)。因此,您必须包含 Container 的定义,以及前向声明的内部类:

class Container {
public:
    class Iterator;
};

然后在一个单独的头文件中,实现 Container::Iterator:

class Container::Iterator {
};

然后 #include 仅容器标头(或不担心前向声明而只包含两者)

于 2009-06-20T15:09:15.863 回答
3

我知道没有办法完全按照您的意愿行事,但如果您愿意使用模板,这里有一个解决方法:

// 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 的并实现了 export ;))。

于 2009-06-20T15:11:32.550 回答