简体   繁体   English

std :: vector的不完整类型

[英]Incomplete type for std::vector

The GCC compiler complains (see below) when I try the following. 当我尝试以下操作时,GCC编译器会抱怨(见下文)。 class Face needs to be incomplete because it contains pointer to class Element which similarly contains pointer to class Face . class Face需要不完整,因为它包含指向class Element指针,类似于包含class Face指针。 In other words, there is a circular dependency among classes. 换句话说,类之间存在循环依赖关系。 How can I fix it? 我该如何解决?

error: invalid application of 'sizeof' to incomplete type 'Face' 错误:'sizeof'无效应用于不完整类型'Face'

class Face; // needs to be incomplete

class Element
{
    std::vector < std::unique_ptr <Face> > face;
};

class Face
{
    std::vector < std::unique_ptr <Element> > elm;
};

One way to fix this is to declare the destructors and constructors of Element and Face but not define them in the header. 解决这个问题的一种方法是声明Element和Face的析构函数和构造函数,但不在头文件中定义它们。 Then you need to define them in cpp files. 然后你需要在cpp文件中定义它们。

(More technical details can be found in the answers to my question there: Is std::unique_ptr<T> required to know the full definition of T? ) (更多技术细节可以在我的问题的答案中找到: std :: unique_ptr <T>是否需要知道T的完整定义?

The source of the problem is that the destructor of unique_ptr needs to call delete (by default) therefore it needs to know the definition of the type (to have it's size). 问题的根源是unique_ptr的析构函数需要调用delete (默认情况下),因此它需要知道类型的定义(具有它的大小)。 But if the destructor of Element and Face is generated automatically, then it will be inlined by default: the code using Element and Face instances will be forced to know the size of both types so that their destructors can call unique_ptr destructor which can call delete with the type associated to the pointer. 但是如果Element和Face的析构函数是自动生成的,那么它将默认内联:使用Element和Face实例的代码将被强制知道两种类型的大小,以便它们的析构函数可以调用unique_ptr析构函数,该析构函数可以调用delete与指针关联的类型。

The solution I gave will make sure the construction and destruction of the unique_ptr are defiend in a separate cpp. 我给出的解决方案将确保unique_ptr的构造和销毁在单独的cpp中是不确定的。 They will not be inlined but they are still callable by the code using Element and Face. 它们不会被内联,但仍可使用Element和Face通过代码调用它们。 The destructor code of the unique_ptrs will be in the cpp where the destructors of Element and Face are defined, so in these cpp the definition of both will be needed. unique_ptrs的析构函数代码将位于cpp中,其中定义了Element和Face的析构函数,因此在这些cpp中将需要两者的定义。

To take your example: 举个例子:

//header
class Face; // needs to be incomplete

class Element
{
public:
    Element(); // don't define it here
    ~Element(); // don't define it here
private:
    std::vector < std::unique_ptr <Face> > face;
};

class Face
{
public:
    Face(); // don't define it here
    ~Face(); // don't define it here
private:
    std::vector < std::unique_ptr <Element> > elm;
};

// cpp 
#include "header"
// if you want the default impl (C++11)
Element::Element() = default; 
Element::~Element() = default; 

Face::Face() = default; 
Face::~Face() = default; 

In case they are in different header/cpp pair, it's still the same solution. 如果它们位于不同的header / cpp对中,它仍然是相同的解决方案。 However you have to do more forward declare and the cpp files defining the construction/destruction have to include all the necessary headers: 但是,您必须执行更多的前向声明,并且定义构造/销毁的cpp文件必须包含所有必需的头:

//element.h
class Face; // needs to be incomplete

class Element
{
public:
    Element(); // don't define it here
    ~Element(); // don't define it here
private:
    std::vector < std::unique_ptr <Face> > face;
};

////////////////////////////////////////////////////////////
// face.h
class Element; // needs to be incomplete

class Face
{
public:
    Face(); // don't define it here
    ~Face(); // don't define it here
private:
    std::vector < std::unique_ptr <Element> > elm;
};

////////////////////////////////////////////////////////////
// element.cpp 
#include "element.h"
#include "face.h" // necessary to allow the unique_ptr destructor to call delete

// if you want the default impl (C++11)
Element::Element() = default; 
Element::~Element() = default; 

////////////////////////////////////////////////////////////
// face.cpp 
#include "element.h" // necessary to allow the unique_ptr destructor to call delete
#include "face.h" 

// if you want the default impl (C++11)
Face::Face() = default; 
Face::~Face() = default; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM