【问题标题】:How to fix an "field has incomplete type" error when using a forward declaration使用前向声明时如何修复“字段类型不完整”错误
【发布时间】:2014-12-25 14:26:31
【问题描述】:

此代码引发编译器错误error: field ‘fTarget’ has incomplete type,如 cmets 中所述。为什么会这样?我只是分配那个字段,而不是做任何需要知道里面是什么的操作……还是我?也许它无法弄清楚复制构造函数?

class FSRVertex;  //fwd

class FSREdge
 {
 public:
    char fC;
    FSRVertex fTarget;   //compiler error
    FSREdge(char c, FSRVertex target) : fC(c), fTarget(target) {}  //compiler error
};


class FSRVertex {
public:
    boost::unordered_map<char, FSREdge> fOutEdges;
    FSRVertex() : fOutEdges() {}
};

【问题讨论】:

    标签: c++ incomplete-type


    【解决方案1】:

    要将 FSRVertex 对象作为类的成员,编译器需要知道其大小,因此需要查看其完整定义。

    要么为你的类提供完整的定义,要么你可以存储一个指针(最好是智能指针),指向在构造函数中执行的对象的动态分配副本。您需要将类外的构造函数主体移动到提供完整定义的位置。这种方法在运行时效率较低。

    【讨论】:

    • 参考也可以。
    • @black 参考一般不会很好,因为会更改所有权。
    • @Slava 那是另一回事。我只是想指出,参考也可以解决这个问题,而不是是否建议这样做。
    • @black 从技术上讲是的,可以解决前向声明的问题。但是对于这个使用参考的具体示例,恕我直言,这不是一个好的答案
    • 我想补充一点,您可以通过模板实现相同的目标。第一个示例 (rextester.com/TLPEJW28982) 将 A 声明为全局类,并在类模板定义之后定义它。作为一个优势,您不必担心在哪里定义 struct A 并避免耦合。第二个示例 (rextester.com/PJCD69132) 将 A 视为 B 的嵌套结构。它编译和运行良好的原因是因为在实例化模板时发生了两阶段查找。有关详细信息,请参阅 C++ 模板:完整指南,10.3.1 两阶段查找。
    【解决方案2】:

    您始终可以将FSRVertex 设为FSREdge 的模板参数。然后编译器必须等待计算FSREdge 的大小,直到专门化并且不知道FSRVertex 的大小不再是问题。这有点傻,但它可以做你想做的,并且没有运行时开销:

    class FSRVertex; // fwd
    
    template <class FSRVertex_Forward = FSRVertex> // make fwd the default type
    class FSREdge_ {
    public:
        char fC;
        FSRVertex_Forward fTarget;
    
        FSREdge_(char c, FSRVertex_Forward target)
            :fC(c), fTarget(target)
        {}
    
        FSREdge_(const FSREdge_ &other) // std::map requires copy ctor
            :fC(other.fC), fTarget(other.fTarget)
        {}
    
        FSREdge_() // std::map requires default ctor
        {}
    };
    
    typedef FSREdge_<> FSREdge; // so that you don't have to carry the brackets everywhere
    
    class FSRVertex {
    public:
        std::map<char, FSREdge> fOutEdges;
        FSRVertex()
            :fOutEdges()
        {}
    };
    

    您可以在ideone 上看到这项工作。

    【讨论】:

      【解决方案3】:

      此错误表示前向声明不充分,您使用该类型的方式。

      你无法修复它。

      【讨论】:

      • 无法修复是什么意思?
      • @NeilKirk:前向声明不能用于必须知道大小的类型。前向声明无法修复。
      • @Neil 好吧,至少你可以高枕无忧了,因为其他三个人也无法理解这种基本的英语。
      • @NeilKirk:您无法进行前向声明。我不知道如何让你更清楚。
      • 您对这个问题的理解太过分了。他想要一些变通办法,我给了一些。
      猜你喜欢
      • 2017-11-07
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-18
      • 1970-01-01
      相关资源
      最近更新 更多