带有智能指针和继承的构造函数的前向声明



根据这个问题,如果所有构造函数和驱动器都不是内联的(然后需要完全定义的类型),则可以转发声明智能指针。如果没有提供击层器,则编译器将声明一个并提供内联定义,然后需要在标题中完全知道智能指针中的类型。默认构造函数也适用。

但是,我发现它也适用于继承的构造函数,这对我来说有点混乱。考虑:

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;
};

除非明确声明Derived构造函数并仅在源文件中定义,否则这不会编译。为什么?Base构造函数不在线,据我所知,使用指令应以与其他成员相似的方式引起构造函数的"继承"。或编译器将其解释为"对我声明与Base中相同的构造函数,并将其定义为字母"?

首先让我们以最小的代码重现问题:

#include <memory>
class SomeClass;
int main()
{
  std::unique_ptr<SomeClass> ptr;
}

错误:

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

这里的同一个问题(证明这与继承无关):

#include <memory>
class SomeClass;
class NotDerived
{
//    ~NotDerived(); //defined in cpp
    std::unique_ptr<SomeClass> ptr;
};
int main(){
  NotDerived d;
}

错误:

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

现在让我们记住什么是唯一的_ptr:

template<
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;

和default_delete ...

在ptr上调用 delete

delete在指针上(到SomeClass)将要破坏Someclass,因此它需要调用SomeClass::~SomeClass

您尚未宣布的。因此错误。

为什么这是相关的?

因为在您的代码中,如果您不声明 Derived的驱动器,则会生成默认值,这当然会称呼ptr的destructor。

在这一点上,编译器将需要SomeClass的完整定义,以便知道如何销毁它。

通过在派生中声明灾难,您将此问题推迟到Derived::~Derived的immentation。

最后一句话是您的答案。编译器将using Base::Base;解释为

"我希望Derived具有与Base相同的签名的构造函数。请为我定义它们。"

对于派生而言,您没有声明构造函数,因此创建了一个默认的构造函数。

默认构造函数或任何其他构造函数称为基本构造函数的事实是另一个与非内联基础构造函数无关的主题。

基本上,除了基类中的构造函数与基类中的构造函数之间没有C 的连接指出,将调用来自基类的默认一个。

相关内容

  • 没有找到相关文章

最新更新