gpt4 book ai didi

c++ - 为什么在使用 PIMPL 习语时这种类型不完整?

转载 作者:搜寻专家 更新时间:2023-10-31 00:56:53 31 4
gpt4 key购买 nike

我正在使用 PIMPL 习语,特别是我正在使用 this post 提供的模板.给定下面的类集并使用 VS2015 Update 3 进行编译,我遇到了编译错误:

Error C2027 use of undefined type 'C::C_impl' (compiling source file src\A.cpp)

Error C2338 can't delete an incomplete type (compiling source file src\A.cpp)

Warning C4150 deletion of pointer to incomplete type 'C::C_impl'; no destructor called (compiling source file src\A.cpp)

我可以通过取消注释 C::~C() 来解决这个问题,这让我相信有什么东西在阻止~C()从自动生成但我不明白是什么。根据this reference ,如果以下任何条件为真,则类型 T 的析构函数被隐式定义为已删除:

  1. T has a non-static data member that cannot be destructed (has deleted or inaccessible destructor)
  2. T has direct or virtual base class that cannot be destructed (has deleted or inaccessible destructors)
  3. T is a union and has a variant member with non-trivial destructor.
  4. The implicitly-declared destructor is virtual (because the base class has a virtual destructor) and the lookup for the deallocation function (operator delete() results in a call to ambiguous, deleted, or inaccessible function.

第 2、3 和 4 项显然不适用于 C ,我不认为#1 适用,因为 pimpl<> (C 的唯一成员)明确定义了一个析构函数。

谁能解释一下这是怎么回事?

啊啊

#pragma once
#include <Pimpl.h>

class A
{
private:
struct A_impl;
pimpl<A_impl> m_pimpl;
};

B.h

#pragma once
#include "C.h"

class B
{
private:
C m_C;
};

C.h

#pragma once
#include <Pimpl.h>

class C
{
public:
// Needed for the PIMPL pattern
//~C();

private:
struct C_impl;
pimpl<C_impl> m_pimpl;
};

A.cpp

#include <memory>
#include "A.h"
#include "B.h"
#include <PimplImpl.h>

struct A::A_impl
{
std::unique_ptr<B> m_pB;
};

// Ensure all the code for the template is compiled
template class pimpl<A::A_impl>;

C.cpp

#include <C.h>
#include <PimplImpl.h>

struct C::C_impl { };

// Needed for the PIMPL pattern
//C::~C() = default;

// Ensure all the code for the template is compiled
template class pimpl<C::C_impl>;

为了完整起见,上面引用的帖子中的 PIMPL 实现:

pimpl.h

#pragma once
#include <memory>

template<typename T>
class pimpl
{
private:
std::unique_ptr<T> m;
public:
pimpl();
template<typename ...Args> pimpl(Args&& ...);
~pimpl();
T* operator->();
T& operator*();
};

PimplImpl.h

#pragma once
#include <utility>

template<typename T>
pimpl<T>::pimpl() : m{ new T{} } {}

template<typename T>
template<typename ...Args>
pimpl<T>::pimpl(Args&& ...args)
: m{ new T{ std::forward<Args>(args)... } }
{
}

template<typename T>
pimpl<T>::~pimpl() {}

template<typename T>
T* pimpl<T>::operator->() { return m.get(); }

template<typename T>
T& pimpl<T>::operator*() { return *m.get(); }

关于上面代码的几点说明:

  • 我正在尝试公开 AC给我图书馆的消费者并保留B内部。
  • 这里没有 B.cpp,它是空的。

最佳答案

您必须在定义 C::C_impl 之后手动定义 C 析构函数,因为默认编译器会尝试在使用时生成 C 析构函数,但它可能是找不到 C::C_impl 定义的地方(例如,它可以是 B.cpp)。

关于c++ - 为什么在使用 PIMPL 习语时这种类型不完整?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38506650/

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