当全局函数需要指向 impl 的指针时,如何防止 impl 细节出现在头文件中?

How to prevent impl details from being in the header file when a global function needs a pointer to the impl?

我在我的代码中大量使用 pimpl idiom,主要是为了减少编译时间。

我遇到了调用 C 库的情况。我有一个 C++ 包装器 class,它有它的接口,血淋淋的细节都在 impl 中,当然:

class some_class {
public:
    void some_init();
    ...
private:
    class impl;
    std::unique_ptr<impl> m_pimpl;
}

在 cpp 文件中,我必须在 C 库中注册一个回调函数,以便为它提供一个指针。我想将此函数调用转发给相应的成员函数。客户端(即此函数的用户)根本不需要知道这个细节:

static void from_c_func(void *ptr_to_class_impl) {
    static_cast<some_class::impl *>(ptr_to_class_impl)->from_c_func();
}

void some_class::some_init() {
    create_c_thing(static_cast<void *>(this->m_pimpl.get()), from_c_func);
}

问题是 some_class::impl 被声明为私有。我只能想到不完美的解决方案:

  1. 在头文件中制作class impl;public。这并不理想,因为它确实应该是 private - 它恰好是一个非 class 函数需要看到它的实现细节。
  2. from_c_func放在头文件中,然后friend。这并不理想,因为 some_class 的实现细节正在泄露。更改实现可能需要更改头文件,然后重新编译很多不需要重新编译的东西,这让我很不高兴。
  3. from_c_func一个指向some_class本身的指针,然后在some_class上调用一个函数。这将需要将该函数放入头文件中,这又是一个实现细节 - 无论如何非友元函数都必须 public 才能调用它。

怎么办?到目前为止,我最好的选择似乎是 #1,但有没有更好的方法?

您可以在 impl

中移动您的函数
static void some_class::impl::from_c_func(void *ptr_to_class_impl) {
    static_cast<some_class::impl *>(ptr_to_class_impl)->from_c_func();
}