我正在尝试创建一个从使用PIMPL习惯用法的基类继承的类。
我有一个基类base.h
:
#include <memory>
class Base {
public:
class Impl;
Base(std::unique_ptr<Base::Impl> impl);
virtual ~Base();
private:
std::unique_ptr<Base::Impl> impl_;
};
在base.cpp
中实现:
#include "base.h"
class Base::Impl {
public:
Impl() {}
~Impl() {}
};
Base::Base(std::unique_ptr<Base::Impl> impl) : impl_(std::move(impl)) {}
Base::~Base() {}
然后在derived.cpp
中派生:
#include "base.h"
class Derived : public Base {
public:
Derived() : Base(nullptr) {}
~Derived() override {}
};
编译这三个文件时,出现以下错误:
In file included from /usr/include/c++/7/memory:80:0,
from base.h:1,
from derived.cpp:1:
/usr/include/c++/7/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Base::Impl]’:
/usr/include/c++/7/bits/unique_ptr.h:268:17: required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Base::Impl; _Dp = std::default_delete<Base::Impl>]’
derived.cpp:5:27: required from here
/usr/include/c++/7/bits/unique_ptr.h:76:22: error: invalid application of ‘sizeof’ to incomplete type ‘Base::Impl’
static_assert(sizeof(_Tp)>0,
哪种方法有意义,因为没有~Impl()
可供派生类使用。在将以下代码段添加到derived.cpp
类定义之前的Derived
之后:
class Base::Impl {
public:
Impl() {}
~Impl() {}
};
它可以编译。 derived.cpp
是否可以使用Impl
中的base.cpp
析构函数,而不将其添加到base.cpp
和derived.cpp
都使用的其他共享文件中?我还注意到,此问题仅是由于构造函数将unique_ptr
引入Base::Impl
而引起的。如果我用只向new Impl
分配Base::impl_
的空构造函数替换该构造函数,则不必像上面那样包含析构函数。在那种情况下有什么不同?