C++ 如何解决“问题”;字段的类型不完整“;使用转发声明时出错

C++ 如何解决“问题”;字段的类型不完整“;使用转发声明时出错,c++,incomplete-type,C++,Incomplete Type,此代码引发编译器错误错误:如注释中所述,字段“fTarget”的类型不完整。为什么会这样?我只分配那个字段,不做任何需要知道里面是什么的操作。。。还是我?也许它不能找出复制构造函数 class FSRVertex; //fwd class FSREdge { public: char fC; FSRVertex fTarget; //compiler error FSREdge(char c, FSRVertex target) : fC(c), fTarge

此代码引发编译器错误
错误:如注释中所述,字段“fTarget”的类型不完整。为什么会这样?我只分配那个字段,不做任何需要知道里面是什么的操作。。。还是我?也许它不能找出复制构造函数

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() {}
};
类FSRVertex//前轮驱动
FSREdge类
{
公众:
char-fC;
FSRVertex fTarget;//编译器错误
FSREdge(char c,FSRVertex目标):fC(c),fTarget(目标){}//编译器错误
};
类FSRVertex{
公众:
混乱的地图污染;
FSRVertex():fOutEdges(){}
};

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


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

此错误意味着转发声明不足,这是您使用该类型的方式


您无法修复它。

您可以始终将
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()
    {}
};
类FSRVertex;//前轮驱动
模板//使fwd成为默认类型
FSREdge_类{
公众:
char-fC;
FSRVertex_前向fTarget;
FSREdge_uu(字符c、FSRVertex_u前向目标)
:fC(c),fTarget(目标)
{}
FSREdge_(const FSREdge_和其他)//std::map需要复制构造函数
:fC(其他.fC)、fTarget(其他.fTarget)
{}
FSREdge_u2;()//std::map需要默认的构造函数
{}
};
typedef FSREdge_FSREdge;//这样你就不必到处带括号了
类FSRVertex{
公众:
地图污染;
FSRVertex()
:foundges()
{}
};

你可以看到这项工作。

你说它不能被修复是什么意思?@NeilKirk:对于必须知道大小的类型,不能使用正向声明。转发声明无法修复。@Neil好吧,至少你可以放心了,因为另外三个人也不懂这个基本的英语。@NeilKirk:转发声明是行不通的。我不知道如何让你更清楚地了解这一点。你把这个问题看得太字面了。他想要一些解决办法,我给了一些。推荐也可以。@black reference一般不会好,因为它会改变所有权。@Slava那是另一回事。我只是想指出,引用也可以解决这个问题,而不是这样做是否明智。@black从技术上说是的,这将解决远期声明的问题。但是对于这个特定的例子,使用reference并不是一个很好的答案,IMHOI只想补充一点,您可以通过模板实现相同的目标。第一个示例(rextester.com/TLPEJW28982)将声明为全局类,并在类模板定义之后定义它。作为一个优势,您不必担心在何处定义结构A,并且可以避免耦合。第二个示例(rextester.com/PJCD69132)将A视为B的嵌套结构。之所以编译并运行良好,是因为在实例化模板时会发生两阶段查找。有关详细信息,请参阅C++模板:完整指南,103.1两阶段查找。