必须在PIMPL中提供析构函数 [英] Must provide destructor in the PIMPL

查看:167
本文介绍了必须在PIMPL中提供析构函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

// main_pimpl_sample.cpp
#include "pimpl_sample.hpp"

using namespace std;

int main()
{
  pimpl_sample p;

  return 0;
}

// pimpl_sample.cpp 

#include "pimpl_sample.hpp"

struct pimpl_sample::impl {
};

pimpl_sample::pimpl_sample()
  : pimpl_(new impl) {
}

// pimpl_sample::~pimpl_sample()
// cause problem if missed
// {}


// pimpl_sample.hpp

#if !defined (PIMPL_SAMPLE)
#define PIMPL_SAMPLE

#include <boost/scoped_ptr.hpp>

class pimpl_sample {
  struct impl;
  boost::scoped_ptr<impl> pimpl_;

public:
  pimpl_sample();
  //~pimpl_sample(); cause problem if missed
  void do_something();
};

#endif


~/Documents/C++/boost $ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2

~/Documents/C++/boost $ g++ -o main_pimpl_sample main_pimpl_sample.cpp pimpl_sample.cpp pimpl_sample.hpp
In file included from /usr/include/boost/smart_ptr/scoped_ptr.hpp:15:0,
                 from /usr/include/boost/scoped_ptr.hpp:14,
                 from pimpl_sample.hpp:6,
                 from main_pimpl_sample.cpp:2:
/usr/include/boost/checked_delete.hpp: In function ‘void boost::checked_delete(T*) [with T = pimpl_sample::impl]’:
/usr/include/boost/smart_ptr/scoped_ptr.hpp:80:9:   instantiated from ‘boost::scoped_ptr<T>::~scoped_ptr() [with T = pimpl_sample::impl]’
pimpl_sample.hpp:8:20:   instantiated from here
/usr/include/boost/checked_delete.hpp:32:58: error: invalid application of ‘sizeof’ to incomplete type ‘pimpl_sample::impl’ 
/usr/include/boost/checked_delete.hpp:32:58: error: creating array with negative size (‘-0x00000000000000001’)

上述编译错误的解决方案手动提供析构函数。显示的原因如下:

The solution to above compilation error is to manually provide a destructor. The indicated reason is as follows:


你必须记住手动定义析构函数;原因
是在编译器生成一个隐式析构函数时,
类型impl是不完整的,所以它的析构函数不被调用。

you must still remember to define the destructor manually; the reason is that at the time the compiler generates an implicit destructor, the type impl is incomplete, so its destructor isn't called.

问题>我仍然有困难吸收上述想法,想知道一些细节为什么我们必须在这里提供手动析构函数。

Question> I still have difficulties to absorb the above idea and would like to know a little detail why we have to provide a manual destructor here.

感谢您

推荐答案


TL; DR 声明一个显式析构函数,并在代码模块中实现它(不在头文件中)。

TL;DR Declare an explicit destructor and implement it in a code module (not in the header file).

t创建析构函数,然后编译器在每个尝试销毁此类的对象的转换单元中创建一个空的自动析构函数。

If you don't create the destructor, then the compiler creates an empty automatic destructor in every translation unit which tries to destroy an object of this class. You'd get equivalent behaviour if you defined an empty inline destructor in the class header.

这会导致一个错误,因为析构函数也负责调用所有类的析构函数'字段,它们按顺序需要实例化方法模板 boost :: scoped_ptr< impl> ::〜scoped_ptr(); 。这个模板不能被实例化,因为它试图删除类型 impl 的一个对象,它只在那个范围内被向前声明(你需要一个完整的定义知道如何删除此对象。

This causes an error because the destructor is also responsible for calling destructors of all the class' fields, which - in order - needs the instantiation of the method template boost::scoped_ptr<impl>::~scoped_ptr();. This template, in turn, cannot be instantiated then because it tries to delete an object of type impl, which is only forward declared in that scope (and you need a full definition to know how to delete this object.

OTOH,如果在标题中声明非内联构造函数,只在 pimpl_sample.cpp 中生成,其中还包含 impl 的定义,因此scoped_ptr的析构函数可以成功实例化。

OTOH, if you declare the non-inline constructor in the header, its code is only generated in pimpl_sample.cpp, where also lies the definition of impl, so the scoped_ptr's destructor can be instantiated successfully.

其他翻译单元只会调用 pimpl_sample 的析构函数作为外部方法,因此他们不需要生成它并自己实例化 scoped_ptr 的析构函数。

Other translation units then only call pimpl_sample's destructor as an external method, so they don't need to generate it and instantiate scoped_ptr's destructor on their own.

这篇关于必须在PIMPL中提供析构函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆