Pimpl Idiom 的嵌套名称说明符中使用的不完整类型

Incomplete type used in nested name specifier for Pimpl Idiom

我遇到以下代码的错误

incomplete type ‘Foo::Pimpl’ used in nested name specifier

AnotherFoo.hpp

struct AnotherFoo {
    void methodAnotherFoo(Foo &);
};

AnotherFoo.cpp

#include "Foo.hpp"
#include "AnotherFoo.hpp"

void AnotherFoo::methodAnotherFoo(Foo &foo) {
    // here i want to save the function pointer of methodPimpl(), std::function for ex:
    std::function<void(void)> fn = std::bind(&Foo::Pimpl::methodPimpl, foo._pimpl); // <-- Here i am getting the error
}

Foo.hpp

struct Foo {
    Foo();
    class Pimpl;
    std::shared_ptr<Pimpl> _pimpl;
};

Foo.cpp

#include "Foo.hpp"

struct Foo::Pimpl {
    void methodPimpl(void) {}    
};

Foo::Foo() : _pimpl(new Pimpl) {}

main.cpp

#include "Foo.hpp"
#include "AnotherFoo.hpp"

int main() {
    Foo foo;
    AnotherFoo anotherFoo;
    anotherFoo.methodAnotherFoo(foo);
}

有没有人有解决此问题的好方法?

我试图实现的主要目标是在头文件中隐藏 methodAnotherFoo 方法的签名。

您可以在其中访问 Foo::Pimpl 详细信息的唯一文件是 Foo.cpp,即定义它的文件。

您可能无法在 AnotherFoo.cpp 中访问它。

您的选择是:

  1. 更改 AnotherFoo::methodAnotherFoo 的实现以仅使用 Foo 的 public 接口。

  2. AnotherFoo::methodAnotherFoo 的实施移动到 Foo.cpp。

如果 AnotherFoo.cpp 需要直接访问实现 object 它将不得不查看该类型的定义,没有办法解决这个问题。也许添加一个 "detail/foo.h" header 供内部使用。

您的 Pimpl 实现不正确。当您尝试直接从 methodAnotherFoo 访问它们时,它应该隐藏详细信息。因此,您应该将实现细节设为私有并提供 public 代理方法来操作存储的实现:

class Foo
{
    public: Foo();

    public: void method(void);

    private: class Pimpl;
    private: std::shared_ptr<Pimpl> _pimpl;
};

// Foo.cpp
struct Foo::Pimpl
{
    void methodPimpl(void) {}    
};

Foo::Foo() : _pimpl(new Pimpl) {}

void Foo::method(void) {_pimpl->method();}

并更改其余代码以利用这些代理方法,而不是挖掘实现细节:

void AnotherFoo::methodAnotherFoo(Foo &foo)
{
    std::function<void(void)> fn = std::bind(&Foo::method, foo);
}

我找到的一个解决方案是将 Pimpl 实现移至 AnotherFoo.cpp