gpt4 book ai didi

c++ - 不是默认析构函数导致不完整的类型错误

转载 作者:太空狗 更新时间:2023-10-29 21:13:10 27 4
gpt4 key购买 nike

这个例子展示了编译器(msvc14、gcc、clang)的奇怪行为,但我没有找到解释。

当我们实现 pipml idiom 并使用前向声明时,我们需要考虑 unique_ptr 具有不完整类型的特定行为。这个案例被提及herehere .

但是当我们将转发类的定义移动到另一个头文件并在稍后使用客户端类时将头文件包含在一个地方时,编译器会变得疯狂 - 在析构函数声明的某些特殊情况下,他们会说不完整的类型。

这是一个最小的例子。如果取消注释“#define CASE_2”或“#define CASE_3”并尝试构建它,将会出现编译错误。

文件 foo.h

#ifndef FOO_H
#define FOO_H

class Foo{};

#endif // FOO_H

文件base.h

#ifndef BASE_H
#define BASE_H

#include <memory>

//#define CASE_1
//#define CASE_2
//#define CASE_3

class Foo;

class Base
{
public:

#if defined(CASE_1)
~Base() = default; // OK!
#elif defined(CASE_2)
~Base() {}; // error: invalid application of 'sizeof' to incomplete type 'Foo'
#elif defined(CASE_3)
~Base(); // error: invalid application of 'sizeof' to incomplete type 'Foo'
#endif

// OK!

private:
std::unique_ptr<Foo> m_foo;
};

#endif // BASE_H

文件base.cpp

#include "base.h"

#if defined(CASE_3)
Base::~Base()
{
}
#endif

文件main.cpp

#include "foo.h"  // No matter order of this includes
#include "base.h" //

int main()
{
Base b;
}

最佳答案

我相信,这与 C++ 标准 12.4/6 有关。

A destructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to destroy an object of its class type (3.7) or when it is explicitly defaulted after its first declaration.

当您的析构函数默认时,它只会在使用 ODR 时被定义,即当 Base 对象被销毁时。在你的代码片段中,没有这种类型的对象被销毁,因此,程序编译 - 因为 unique_ptr 的 deleter 实际上并没有在任何地方调用 - 它只被 Base 析构函数调用,它没有定义在这种情况下。

当您提供一个用户定义的析构函数时,它是就地定义的,并且程序变得格式错误,因为您无法析构不完整类型的 unique_ptr 对象。

顺便说一句,析构函数声明,但不是定义(如~base();)不会产生编译错误同样的道理。

关于c++ - 不是默认析构函数导致不完整的类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45328143/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com