0

複数のプラットフォームで動作するように一部のソフトウェアを書き直すことができるように、C++ フレームワークを作成しています。Windows ハンドルを使用する一部のラッパー クラスの実装に関する質問です。次のコードを検討してください...

class Font
{
public:
  Font(const LOGFONT& lf)
  {
    m_hFont = ::CreateFontIndirect(lf);
  }

  ~Font()
  {
     ::DeleteObject(m_hFont);
  }

private:
  HFONT m_hFont;
}

次に、次のように呼び出す可能性のある Display クラスがあります...

LOGFONT lf;
// initialise lf

Display d;
d.SetFont(Font(lf));
d.DrawText(0,0,"Some Text");

もちろん問題は、d.SetFont によって、Font クラスのデストラクタによって m_hFont が削除されることです。ヒープ上にフォントを作成し、フォントの全体的な「寿命」をグラフィックス クラスに任せることができたことに感謝します。これは本当に設計上の問題だと思います。したほうがいいのでしょうか...

  1. Windows ハンドルをラップするクラスの参照カウントを実装します。
  2. ヒープにラッパー クラスを作成します。
  3. 他の方法?

MFC のラッパーには明示的な DeleteObject があることに気付きましたが、もちろん、これによってリソースの割り当てが自動的に解除されるわけではありません。

ヘルプ/アドバイスをいただければ幸いです。

ありがとう

編集:これはコピーコンストラクターの質問だと思います。つまり、私の Font クラスは Windows FONT ハンドルを作成しますが、Font オブジェクトを値でディスプレイに渡すため破棄されます。

4

3 に答える 3

1

少なくとも 3 つのオプションがあります。

  1. 「3 つのルール」に注意してください。クラスに重要なデストラクタがある場合は、おそらくコピー コンストラクタとコピー代入演算子も実装する必要があります。この場合、すべてのコピーに独自のバージョンのm_hFont.

  2. 参照カウントを使用します。

  3. または const 参照Display::SetFontへのポインターを受け入れるように変更します。Fontそうすれば、「スタック上」を引き続き作成できFont、ポインターまたはそれへの参照のみを渡す場合、コピーは作成されません。

編集

  1. Display::SetFont直接受け入れるようにすると、問題を完全に回避できる場合がありますLOGFONT。このように、Displayクラス自体がフォントを管理します (たとえば、古いフォント構造を削除して新しい構造を作成します)。Fontこのオプションは、オブジェクトを上記のコンテキスト ( を使用) でのみ使用する予定でDisplay、フォントの変更が少ない場合に最適です。

  2. Fontクラスにも をLOGFONTメンバーとして保持させ、オンデマンドでのみ HFONT を生成します。コピーするLOGFONTと、 がコピーされHFONT、 に無効な値が与えられます。newFont::GetFontが呼び出されると (たとえば、 によってDisplay)、HFONTが作成されます。Font デストラクタでHFONT、無効な値でない場合は削除します。CreateFontIndirectこれにより、すべてのコピーが の呼び出しに使用されない場合に、への不要な呼び出しが回避されますGetFont

于 2013-03-29T19:03:03.110 に答える
0

それが Windows の性質です。CreateFontIndirect を呼び出すなどの方法でリソースを使用する場合、作業が終わったら、DeleteObject または何らかのメソッドを呼び出してリソースを解放する必要があります。問題は正確には何ですか?あなたのプログラムは期待どおりに動作していませんか? 使用する前に lf が範囲外にならなければ問題ないはずです。

于 2013-03-29T18:38:21.993 に答える