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

Tree structure with incomplete types and unique_ptr

本文关键字:ptr 结构 unique 类型      更新时间:2023-10-16

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

我所要做的是,对于每个需要销毁不完整类型的类,我必须在.cpp文件中包含相关的头文件。明确定义医生没有帮助,这让我很惊讶。

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头文件?

析构函数的类型应该是完整的,但是析构函数是内联自动生成的,所以这意味着类被销毁的每个地方都应该有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;
};

#include <Level3.h>
Level3Vector::~Level3Vector() = default;

则其它类Level3Vector的破坏不需要<Level3.h>的加入。

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

考虑到这一点,让我们检查你的问题"是否每个可能使用Level2Vector的类都需要包含Level2.h头文件?"答案是否定的。Level2.h提供了类Level2的定义。所以正确的看待方法是:如果文件需要Level2的定义,那么文件(无论是否使用Level2 vector)需要包含Level2.h。