【问题标题】:Incomplete type error while using a nested class in a set在集合中使用嵌套类时出现不完整的类型错误
【发布时间】:2014-03-31 18:39:56
【问题描述】:

我正在将一些 Java 代码翻译成 C++。当我尝试编写如下代码时:

.h:

class A {
  private:
    class B;
    std::set<B> b_set;
};

.cpp:

class A::B {
};

我收到了不完整的类型错误。我知道这是因为嵌套类在b_set 中使用之前是不完整的。但是最好的解决方法是什么?

【问题讨论】:

    标签: c++ nested-class incomplete-type


    【解决方案1】:

    您可以在.h 文件中描述您的整个B 类。

    这是一个工作示例。

    #include<set>
    class A {
      private:
        class B{
            B():foo(1){}
            int foo;
        };
        std::set<B> b_set;
    };
    

    但是,如果您想将定义和实例化分开,您可以这样做:

    啊.h

    #include<set>
    class A {
    
      private:
        class B{
          public:
          B();
          private:
          int someMethod();
          int foo;
        };
        std::set<B> b_set;
    };
    

    A.cpp

    #include "A.h"
      A::B::B():foo(1){}
      int A::B::someMethod(){
        return 42;
      }
    

    一般来说,嵌套类可能是一个严重的 PITA,因为您必须跳过所有的圈子才能访问其中的任何内容。

    另一个关于嵌套类的好参考:Nested class definition in source file

    【讨论】:

    • 谢谢安迪!但在这种情况下,实现是在“.h”文件中。这是一个好习惯吗?
    • @xieziban:看我的编辑。对于使用嵌套类,您需要一个非常好的论据,因此一揽子声明它根本没有。
    【解决方案2】:

    好吧,我来晚了,我知道,我还是想指出另一种可能,如果你想完全隐藏B类的内部:

    class A
    {
      private:
      class B;
      std::set<B*> b_set;
    };
    

    注意在集合中使用指针。但是,还有一个重要的区别:由于只插入了指针,您仍然可以插入指向具有相同内容的不同实例的指针。要解决这个问题,您需要一个自定义比较器:

    class A
    {
      private:
      class B;
      struct Less
      {
        bool operator() (B const* x, B const* y) const
        {
          return *x < *y;
        }
      };
      std::set<B*, Less> b_set;
    };
    

    请注意(这在上一个答案中没有提到,但在那里也是必需的!)必须为 B 定义一个比较器(B 或引用,not 指针!):

    啊.h

    #include <set>
    class A
    {
      private:
      class B;
      struct Less
      {
        bool operator() (B const* x, B const* y) const;
      };
      std::set<B*, Less> b_set;
    };
    

    A.cpp

    class A::B
    {
      friend bool Less::operator() (B const* x, B const* y) const;
      bool operator<(B const& other) const
      {
        return foo < other.foo;
      }
      int foo;
    };
    
    bool A::Less::operator() (B const* x, B const* y) const
    {
      return *x < *y;
    }
    

    如果您出于任何原因想要或需要,这允许从标题中完全隐藏 B。但是,您不能再直接从堆栈中插入对象,因为它们不会被复制,并且您有指向堆栈的指针很快就会变得无效。当不再需要对象时,必须特别注意删除对象,否则会出现内存泄漏。请记住,Java 中没有垃圾收集。如果使用 C++11,可以使用 ::std::unique_ptr, before, ::std::auto_ptr: 来缓解问题:

    啊.h

    #include <set>
    #include <memory>
    class A
    {
      private:
      class B;
      struct Less
      {
        bool operator() (B const* x, B const* y) const;
      };
      std::set<std::unique_ptr<B>, Less> b_set;
    };
    

    【讨论】:

    • 你的回答对我很有帮助。thnx
    猜你喜欢
    • 2012-05-17
    • 2015-10-27
    • 2021-02-19
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 2013-04-29
    • 1970-01-01
    相关资源
    最近更新 更多