Res*_*ion 2 c++ constructor smart-pointers forward-declaration c++11
根据这个问题,如果所有构造函数和析构函数都不是内联的(则需要完全定义的类型),则可以转发声明智能指针。当未提供析构函数时,编译器将声明一个析构函数并提供内联定义,该定义随后要求标头中完全已知智能指针中的类型。这同样适用于默认构造函数。
然而,我发现它也适用于继承的构造函数,这对我来说有点令人困惑。考虑:
class Base
{
public:
Base(); //defined in cpp
};
class SomeClass;
class Derived : public Base
{
using Base::Base;
~Derived(); //defined in cpp
std::unique_ptr<SomeClass> ptr;
};
Run Code Online (Sandbox Code Playgroud)
Derived除非显式声明构造函数并仅在源文件中定义,否则不会编译。为什么?构造函数Base不是内联的,据我所知,using 指令应该以与其他成员类似的方式导致构造函数的“继承”。或者编译器是否将其解释为“为我声明与中相同的构造函数Base并内联定义它们”?
首先让我们用最少的代码重现问题:
#include <memory>
class SomeClass;
int main()
{
std::unique_ptr<SomeClass> ptr;
}
Run Code Online (Sandbox Code Playgroud)
错误:
In file included from /opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/memory:81:0,
from <source>:1:
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = SomeClass]':
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h:236:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = SomeClass; _Dp = std::default_delete<SomeClass>]'
<source>:7:30: required from here
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h:74:22: error: invalid application of 'sizeof' to incomplete type 'SomeClass'
static_assert(sizeof(_Tp)>0,
^
Compiler exited with result code 1
Run Code Online (Sandbox Code Playgroud)
这里同样的问题(证明这与继承无关):
#include <memory>
class SomeClass;
class NotDerived
{
// ~NotDerived(); //defined in cpp
std::unique_ptr<SomeClass> ptr;
};
int main(){
NotDerived d;
}
Run Code Online (Sandbox Code Playgroud)
错误:
In file included from /opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/memory:81:0,
from <source>:1:
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = SomeClass]':
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h:236:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = SomeClass; _Dp = std::default_delete<SomeClass>]'
<source>:5:7: required from here
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h:74:22: error: invalid application of 'sizeof' to incomplete type 'SomeClass'
static_assert(sizeof(_Tp)>0,
^
Compiler exited with result code 1
Run Code Online (Sandbox Code Playgroud)
现在让我们记住 unique_ptr 到底是什么:
template<
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
Run Code Online (Sandbox Code Playgroud)
和default_delete ...
调用
deleteptr
并且delete在指针 (to SomeClass) 上将想要破坏Someclass,因此需要调用SomeClass::~SomeClass
您尚未声明。因此出现了错误。
为什么这很重要?
因为在你的代码中,如果你没有声明 的析构函数Derived,则会生成一个默认的析构函数,这当然会调用 的析构函数ptr。
此时,编译器将需要 的完整定义,SomeClass以便知道如何销毁它。
通过在 Derived 中声明析构函数,您可以将此问题推迟到 的实现Derived::~Derived。