【问题标题】:How do I forward declare an inner class? [duplicate]如何转发声明内部类? [复制]
【发布时间】:2009-06-20 14:58:35
【问题描述】:

我有这样的课......

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

【问题讨论】:

    标签: c++ forward-declaration


    【解决方案1】:

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

    您需要执行以下操作之一

    • 使类非嵌套
    • 更改您的声明顺序,以便首先完全定义嵌套类
    • 创建一个既可以在函数中使用又可以由嵌套类实现的通用基类。

    【讨论】:

    • 通用基类是我最常用的解决方案。
    • @Nikerboker 他们说嵌套类不能在容器外部前声明。链接中的示例是向前声明一个嵌套类在容器的定义中,这是一个不同的场景。
    • 不可能在容器外转发声明嵌套结构这一事实似乎是 C++ 中的一个限制,并且应该是可能的。正确的?有什么原因导致这是不可能的吗?
    • @Wolf 你说得有道理。难道不能通过在前向声明表达式中包含修饰符来指定吗?例如。 class Container::(public Iterator),或者类似的东西? (我不是在谈论今天的语言设计方式,而是在理论上如何设计它。)
    【解决方案2】:

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

    class Container {
    public:
        class Iterator;
    };
    

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

    class Container::Iterator {
    };
    

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

    【讨论】:

    • 很好的答案,除了第一段括号中的部分。在这种情况下,“无法知道是否真的存在内部类”是没有意义的,准确度值得怀疑。前向声明的全部意义在于你告诉编译器有一个类(或者在这种情况下是一个内部类)。您的特定声明与普通类一样,意味着您不能转发声明任何内容。
    【解决方案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 的并实现了导出;)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-07
      • 2014-03-23
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多