【问题标题】:Smart Pointers, Forward Declaration, and C4150智能指针、前向声明和 C4150
【发布时间】:2011-06-14 02:55:36
【问题描述】:

因此,作为一个大型爱好学习项目的一部分,我实现了一个几乎完整的智能指针实现。它几乎可以完成我要求的所有事情,除了一个小细节,如果我无法解决它可能会破坏交易。人为的例子:

//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,没问题。我真的不想在这一点上进行重构。

我听说 boost 智能指针以某种方式解决了这个问题。引入提升不是这个项目的目的,因为它几乎是一个爱好/学习项目。那么 boost 是如何处理这个问题的呢?在这种情况下,如何让智能指针表现得像原始指针一样?我有一些想法,但我认为将问题浮动到 SO 可以将想法列表筛选为有用的子集。

转发感谢您帮助我解决这个问题。

【问题讨论】:

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


【解决方案1】:

那么 boost 是如何处理这个问题的呢?

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

【讨论】:

  • @James:没错。没有其他“解决方案”,请参阅我链接的问题作为对您问题的评论。
【解决方案2】:

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

shared_ptr 构造函数是一个模板,它获取一个指向删除对象的模板函数的指针。由于它是在模板的构造函数中完成的,因此类只需要在构造对象时完成。所有其他操作都可以在没有完全访问权限的情况下执行。

【讨论】:

    【解决方案3】:

    这可以通过在 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
    

    之所以起作用,是因为 SmartPointer 的析构函数是从编译器在 B 的析构函数中生成的代码中调用的,但 ~B 的定义位置取决于您。如果您根本不指定它,它将在 Header2.h 中生成,其中缺少定义,因此会发出警告。如果你在 Header2.cpp 中指定它并将通常的声明放在 Header2.h 中,它显然会在 Header2.cpp 中正常工作,因为在那里知道完整的定义。其他翻译单元,如 Header1.cpp 也可以正常工作,因为它们会看到 ~B 的声明并且不会尝试在现场生成一个。相反,他们只会通过符号调用 ~B,这将由链接器稍后解决。

    在某些情况下,您可能还需要将 B 的赋值运算符和/或出于某种莫名其妙的原因,甚至是构造函数移至 cpp。

    【讨论】:

      猜你喜欢
      • 2020-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-21
      • 1970-01-01
      相关资源
      最近更新 更多