使用前向声明时如何修复“字段类型不完整”错误

Posted

技术标签:

【中文标题】使用前向声明时如何修复“字段类型不完整”错误【英文标题】: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() 
;

【问题讨论】:

【参考方案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:您无法进行前向声明。我不知道如何让你更清楚。 您对这个问题的理解太过分了。他想要一些变通办法,我给了一些。

以上是关于使用前向声明时如何修复“字段类型不完整”错误的主要内容,如果未能解决你的问题,请参考以下文章

不完整类型的无效使用,前向声明不起作用

英特尔编译器不编译另一个类中的私有前向类声明

前向声明 cv::Mat

将结构前向声明为类时出现 Visual C++ 2015 链接器错误

循环依赖结构,使用前向声明时重新定义结构错误

为啥我不能使用双冒号在命名空间中前向声明一个类?