智能指针,前瞻声明和C4150

时间:2011-01-23 18:37:50

标签: c++ smart-pointers forward-declaration

因此,作为大型业余爱好学习项目的一部分,我实现了一个基本上完整的智能指针实现。它几乎可以满足我的所有要求,除了一个小细节,如果我无法解决它可能会被证明是一个交易破坏者。对象示例:

//Header1.h

#include <Header2.h>

class A
{
//Methods and such that involve class B in return type / arguments
};

//Header2.h

class A; //Forward declaration of A, needed because A includes Header2.h

class B
{
public:
    SmartPointer<A> Ptr;
};

您可以猜到,之前的代码为我提供了warning C4150: deletion of pointer to incomplete type 'type'; no destructor called。我知道为什么会这样;在Header2.h中,智能指针代码包括对前向声明的A实例的删除。如果我可以包含Header1.h,那没问题。我真的不希望在这一点上进行重构。

我听说过升级智能指针解决了这个问题,不知何故。引入提升并不是这个项目的目的,因为它几乎是一个爱好/学习项目。那么如何提升这个问题呢?在这种情况下,我怎样才能使智能指针像原始指针一样?我有一些想法,但我认为将问题浮动到SO可以将想法列表剔除到一个有用的子集中。

向前宣布我的谢意,帮助我解决这个问题。

3 个答案:

答案 0 :(得分:2)

  

那么增强如何处理这个问题呢?

通过在智能指针类模板中使用checked_delete而不是delete,Boost处理此问题,因此需要A的完整定义。

答案 1 :(得分:1)

Boost维护一个指向函数的指针,该函数可用于删除对象。它将它与实际指针一起存储在指针对象中。如果你想做除了调用delete之外的其他事情,你可以传递你自己的析构函数。

shared_ptr构造函数是一个模板,它获取指向删除对象的模板函数的指针。由于它是在模板中的构造函数中完成的,因此只有在构造对象时才必须完成类。无需完全访问即可执行所有其他操作。

答案 2 :(得分:0)

这可以通过在B类的CPP文件中定义析构函数(甚至是一个空的析构函数)来解决,如下所示:

//Header1.h
class A
{
//Methods and such that involve class B in return type / arguments
};


//Header2.h

class A; //Forward declaration of A

class B
{
public:
    ~B();

    SmartPointer<A> Ptr;
};


//Header2.cpp
#include "Header2.h"
#include "Header1.h" // obtain full definiton of A

B::~B() = default; // destructor here knows full definition of A

之所以可行,是因为正在从B的析构函数中的编译器生成的代码中调用SmartPointer的析构函数,但是〜B的定义取决于您。如果根本不指定它,它将在Header2.h中生成,其中缺少定义,因此出现警告。如果您在Header2.cpp中专门添加它,并将通常的声明放在Header2.h中,则显然可以在Header2.cpp中正常工作,因为在那里已了解完整的定义。其他翻译单元(例如Header1.cpp)也将正常工作,因为它们将看到〜B的声明,并且不会尝试立即生成该声明。相反,他们只是通过符号调用〜B,稍后将由链接程序解决。

在某些情况下,您可能还需要将C的B的赋值运算符和/或(出于某种无法解释的原因,甚至是构造函数)移至cpp。