0

次のようにヘッダーで定義されたクラスがあります(省略):

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

cairo_t と cairo_surface_t は、Cairoグラフィックス ライブラリによって定義された型です。

私が抱えている問題は、このクラスまたは別のライブラリまたはアプリケーションから派生したクラスを使用する場合、CairoRenderer ヘッダーを介して cairo 型を「リーク」しているため、cairo ヘッダーも含める必要があることです。同じライブラリ内のこのクラス (またはそのサブクラス) を、cairo ヘッダーをインクルードしたり、cairo ライブラリにリンクしたりする必要なく、外部で使用できるようにしたいと考えています。

次に試したのは、ウィキペディアの例に従って 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'

私はにきびを間違っていますか?それとも私がやりたいことは可能ですか?

4

3 に答える 3

4

pimpl イディオムを正しく使用しており、それが問題です。派生クラスのコードを含むすべての外部コードCairoRendererImplからの定義を非表示にしました。

まず、データ メンバーと非仮想デストラクタを持つ基本クラスを持つことの価値に疑問を投げかけたいと思います。をサブクラス化する根本的な理由を調べ、CairoRenderer別の解決策を検討する必要があります。

ライブラリ内のクラスに対してのみサブクラス化をサポートたい場合は、階層内CairoRendererImplのすべての関連クラスの実装ファイルに含めることができる共有ヘッダー ファイルにの定義を配置する必要がありますCairoRenderer

于 2011-10-13T12:50:58.650 に答える
1

にきびのイディオムは大丈夫です。

cairo.h ファイルを含める必要を回避する方法は、CairoRenderer.h ファイルにステートメント (つまり、前方宣言)を含めることです。

class CairoRendererImpl;

そのままにしておきます。cairo.h の定義をドラッグする必要があるため、CairoRendererImpl.h を含めないでください。

CairoRenderer は実装へのポインターのみを必要とするため、これを行うことができます。実際にヘッダーファイル (インライン関数など) からメソッドを呼び出さない限り、コンパイラーは CairoRendererImpl クラスの完全な宣言を確認する必要はありません。

CairoRenderer.cc に CairoRendererImpl.h ファイルを含めることができます (これは cairo.h のものを取得しますが、この時点で実際に必要/必要なものです)。

h番目、h

于 2011-10-13T13:12:43.283 に答える
0

struct CairoRenderer::CairoRendererImplは間違っていると思います。名前空間を使用しないため、次のような単純な定義で十分です。

struct CairoRendererImpl 
{
    ...
}

CairoRendererまた、クラスを少し調整する必要があります。

struct CairoRendererImpl;

class CairoRenderer
{
...
protected:
    CairoRendererImpl* m_pimpl;
};
于 2011-10-13T12:47:16.533 に答える