在集合中使用嵌套类时出现不完整的类型错误

Incomplete type error while using a nested class in a set

本文关键字:错误 类型 集合 嵌套      更新时间:2023-10-16

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

.h:

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

。.cpp:

class A::B {
};

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

您可以在

.h文件中描述整个B类。

这是一个工作示例。

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

但是,如果要分离定义和实例化,可以执行以下操作:

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

答.cpp

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

一般来说,嵌套类可能是一个严肃的PITA,因为您必须跳过所有障碍才能从它们访问任何内容。

关于嵌套类的另一个很好的参考:源文件中的嵌套类定义

好吧,我迟到了,我知道,我还是想指出另一种可能性,如果你想完全隐藏 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或参考,而不是指针!

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

答.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 缓解问题,之前使用 ::std::auto_ptr:

#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;
};