我在标题中定义了一个这样的类(缩写):

class CairoRenderer
{
public:
    CairoRenderer();
    ~CairoRenderer();
...
protected:
    cairo_t* m_context;
    cairo_surface_t* m_surface;
};


cairo_t和cairo_surface_t是Cairo图形库定义的类型。

我遇到的问题是,如果要使用此类或从另一个库或应用程序衍生的类,我还需要包括cairo标头,因为我是通过CairoRenderer标头“泄漏” cairo类型的。我希望同一类库中的此类(或其任何子类)可在外部使用,而无需包括cairo标头或针对cairo库的链接。

因此,我接下来尝试根据Wikipedia示例使用pimpl技术,因为它看起来可以完成我想实现的目标:

CairoRenderer.h(缩写)

class CairoRenderer
{
...
protected:
    struct CairoRendererImpl;
    CairoRendererImpl* m_pimpl;
};


CairoRenderer.cpp(缩写)

#include "CairoRenderer.h"
#include "cairo.h"

....

struct CairoRenderer::CairoRendererImpl
{
public:
    CairoRendererImpl() : m_surface(NULL), m_context(NULL) { }
    ~CairoRendererImpl()
    {
        cairo_surface_destroy(m_surface);
        cairo_destroy(m_context);
    }

    void Initialize(cairo_t* context, cairo_surface_t* surface)
    {
        m_context = context;
        m_surface = surface;
    }

    cairo_surface_t* surface() { return m_surface; }
    cairo_t* context() { return m_context; }

private:
    cairo_surface_t* m_surface;
    cairo_t* m_context;
};

CairoRenderer::CairoRenderer() : m_pimpl(new CairoRendererImpl()) { ... }

CairoRenderer::~CairoRenderer() { delete m_pimpl; }


我遇到的问题是,当我尝试从派生类访问m_pimpl成员时,出现编译器错误:

error C2027: use of undefined type 'CairoRenderer::CairoRendererImpl'


我做错了pimpl吗?还是我想做的可能?

最佳答案

您正在正确使用pimpl习惯用法,这就是您的问题。您已从所有外部代码(包括派生类中的代码)中隐藏了CairoRendererImpl的定义。

首先,我想质疑具有包含数据成员和非虚拟析构函数的基类的价值。您应该查看想要将CairoRenderer子类化的根本原因,并考虑其他解决方案。

如果确实要支持子类化,但仅支持库中的类,则应将CairoRendererImpl的定义放入共享的头文件中,该文件可以包含在希拉希。

09-07 14:47