具有不完整类型和unique_ptr的树结构

时间:2016-10-13 21:06:40

标签: c++ c++11

我有关于不完整类型和unique_ptr的快速问题。 我试图有一个简单的树类型结构,这里已经简化了,我得到了一些关于不完整类型的编译器错误,我知道我必须定义dtor。虽然这没有解决问题,至少在msvc我正在测试它。

我需要做的是,对于每个需要销毁不完整类型的类,我必须在.cpp文件中包含相关的标题。明确定义dtor并没有帮助,这让我感到惊讶。

Level1.h

#include "Level2Vector.h"

class Level1
{
public:
    Level1() : lvl2_vec(this) {}

private:
    Level2Vector lvl2_vec;
};

Level1.cpp

#include "Level2.h" // this was needed to not get the incomplete type
#include "Level3.h" // this was needed to not get the incomplete type 

Level2.h

#include "Level3Vector.h"

class Level1;

class Level2
{
public:
    Level2(Level1* const lvl1) : parent_(lvl1), lvl3_vec(this){}

private:
    Level1* parent_;
    Level3Vector lvl3_vec;
};

Level2.cpp

#include "Level2.h"
#include "Level3.h"  // this was needed to not get the incomplete type

Level3.h

class Level2;

class Level3
{
public:
    Level3(Level2* const lvl2) : parent_(lvl2) {}

private:
    Level2* parent_;
};

Level2Vector.h

class Level1;
class Level2;

class Level2Vector : public std::vector<std::unique_ptr<Level2>>
{
public:
    Level2Vector(Level1* lvl1) : parent_(lvl1) {}

private:
    Level1* parent_;
};

Level3Vector.h

class Level2;
class Level3;

class Level3Vector : public std::vector<std::unique_ptr<Level3>>

{
public:
    Level3Vector(Level2* lvl2) : parent_(lvl2) {}
    //~Level3Vector();

private:
    Level2* parent_;
};

我错过了什么吗? 是否每个可能使用的类都说Level2Vector需要包含Level2.h标题?

2 个答案:

答案 0 :(得分:1)

析构函数的类型应该是完整的,但是析构函数是内联自动生成的,这意味着销毁类的每个地方都应该通过std::unique_ptr定义类所拥有的。

避免此问题的简单方法是为每个具有std::unique_ptr成员的类声明析构函数。所以:

class Level3Vector
{
public:
    explicit Level3Vector(Level2* lvl2) : parent_(lvl2) {}
    ~Level3Vector();

    // And so rule of 5
    Level3Vector(const Level3Vector&) = delete;
    Level3Vector& operator =(const Level3Vector&) = delete;

    Level3Vector(Level3Vector&&) = default;
    Level3Vector& operator =(Level3Vector&&) = default;

private:
    std::vector<std::unique_ptr<Level3>> lvl3s;
    Level2* parent; // or std::observer_ptr<Level2> parent;
};

在cpp:

#include <Level3.h>

Level3Vector::~Level3Vector() = default;

然后在其他类中销毁Level3Vector不需要包含<Level3.h>

答案 1 :(得分:0)

一般来说,您可以使用前向声明的类型(例如在头文件中使用该类型定义指针);但是在需要定义类型之前,必须提供类型的定义。例如。在Level1.h中,您定义了Level2Vector类型的对象(不是指向Level2Vector的指针!);所以Level1.h必须包含Level2Vector.h。

考虑到这一点,让我们检查你的问题&#34;每个可能使用Level2Vector的类是否需要包含Level2.h标题?&#34;答案是不。 Level2.h提供了Level2类的定义。因此,查看它的正确方法是:如果文件需要Level2的定义,则文件(使用Level2Vector或不使用Level2.h)需要包含Level2.h。