クラス構造を作成するときに、結構困るのが、エラー情報の伝達方法。
エラーの有無が重要な場合や、エラー情報が1つだけの場合だったら、関数の戻り値にboolや文字列クラスを使用することで、なんとかなるかも知れないけど、エラーが起きたら、処理を中断することばかりではない。 処理を継続して、最終的に複数のエラーを伝えたいこともあるし、下流で起こったエラーを上流に伝えるときに、さらにエラー情報を補足したい事もよくある。 また、エラー処理の定石の try~catch 句は、こういう問題を解決するためのものではない。 こんな時に利用できるのが次みたいなクラス。 #include <list> #define MAX_ERROR_LENGTH 511 class ErrorQueue { ErrorQueue(){} virtual ~ErrorQueue() = 0; // オーバーライドを要求 protected: std::list<CString> m_errorQueue; // エラー情報を保存 void SetError(const char *format, ...) { char buffer[MAX_ERROR_LENGTH+1]; va_list errmsg; va_start(errmsg, format); vsprintf(buffer, format, errmsg); va_end(errmsg); m_errorQueue.push_back(buffer); } public: bool GetNextError(CString& strError) // エラー情報を取り出す { if(m_errorQueue.empty()) return false; strError = m_errorQueue.front(); m_errorQueue.pop_front(); return true; } }; このクラスでは、STLのリストを使用して、エラー情報をキャッシュしている。 STLのqueueを使っているわけじゃないけど、外部クラスへは、キューに近いインターフェースを公開しているのでクラス名にはQueueを付けた。 ErrorQueueクラスは、純粋仮想関数なので、他のクラスに継承させてから使用しなければいけない。 基本的には、このようなエラー処理が必要になった既存のクラスに多重継承で(無理矢理 ^^;) くっつける。 派生クラスの中でエラーが発生したら、何回でも SetError() 関数を呼び出して、リストにエラー情報を貯めておくことが出来る。 ↓はエラー登録コードのイメージです。 bool CXYZ::DoAllProcesses() { bool ok = true; for(int i=0; i<count; i++) { CString& strFileName = m_fileList[i]; if(!DoProcess(strFileName )) { SetError("処理に失敗しました: %s", strFileName); ok = false; } } return ok; // 成功か失敗かは上流に知らせる } クライアントコードからは、次のように while ループで全てのエラー情報を取得できる。 ... if(!xyz.DoAllProcesses()) { // 全てのエラー情報をファイルに書き出す CString errMsg; while(obj.GetNextError(errMsg)) { logFile.Write("This Class Name : %s\n", errMsg); } AfxMessageBox("エラーが発生しました。ログファイルを確認して下さい。"); } ... また、次のように直前のメッセージに追記する関数をErrorQueueクラスに追加して、その次のようなマクロを作って、エラーの発生場所と時間なんかを自動的に書き出してくれるようにすると、後々楽かも。 // 直前のエラー情報に追記 void AppendError(const char *format, ...) { char buffer[MAX_ERROR_LENGTH+1]; va_list errmsg; va_start(errmsg, format); vsprintf(buffer, format, errmsg); va_end(errmsg); m_errorQueue.back() += buffer; } // タイムスタンプ・ファイル名・行番号を付加 #define SETERROR SetError("%s %s, %s(%d), " \ , __DATE__, __TIME, __FILE__, __LINE__); \ AppendError また、m_errorQueue をスタティック変数にすれば、全てのエラーを時系列で取得することも出来るし、キューに入れずにファイルに書き出すようにすれば、ログファイルの作成にも役立つかも。 ANSI準拠にするには、CString を std::string に変えるだけでOKなはず。
MFCを使っていると、文字列クラスは必ず CString になってしまう。 しかも、無理に std::string を使おうと思うと、必ずごちゃ混ぜになって、かなり醜いコードになってしまう (;_;)
by isoq
| 2005-04-21 18:09
| C/C++/Win32
|
PR
検索
最新の記事
カテゴリ
全体 開発日記 コンピュータ C/C++/Win32 Ubuntu / Linux Web データベース 3Dグラフィックス スクリプティング 書籍 - 技術系 フリーウェア モバイル 日記 子供のこと 旅行日記 観察日記 グルメ 写真館 天体観測 ショッピング アートワーク ヘルスケア 携帯からの投稿 誤変換検索 趣味 Windows 未分類 タグ
海外
Windows 7
旅行
C++
ドイツ
Windows
Aspire 1410
ボストン
MFC
OpenGL
出張
REGZA
天体望遠鏡
お買い得
CUDA
42Z9000
GPGPU
グルメ
XPモード
NaiNai
最新のトラックバック
以前の記事
2022年 03月 2020年 05月 2020年 04月 2020年 03月 2018年 05月 2016年 02月 2015年 04月 2015年 03月 2013年 10月 2012年 01月 2011年 12月 2011年 11月 2011年 10月 2011年 09月 2011年 08月 2011年 07月 2011年 06月 2011年 05月 2011年 03月 2011年 02月 2011年 01月 2010年 11月 2010年 10月 2010年 09月 2010年 08月 2010年 07月 2010年 06月 2010年 05月 2010年 04月 2010年 03月 2010年 02月 2010年 01月 2009年 12月 2009年 11月 2009年 10月 2009年 09月 2009年 08月 2009年 07月 2009年 06月 2009年 05月 2009年 04月 2009年 03月 2009年 02月 2009年 01月 2008年 12月 2008年 11月 2008年 10月 2008年 09月 2008年 08月 2008年 07月 2008年 06月 2008年 05月 2008年 04月 2008年 03月 2008年 02月 2008年 01月 2007年 12月 2007年 11月 2007年 10月 2007年 09月 2007年 08月 2007年 07月 2007年 06月 2007年 05月 2007年 04月 2007年 03月 2007年 02月 2007年 01月 2006年 12月 2006年 11月 2006年 10月 2006年 09月 2006年 08月 2006年 07月 2006年 06月 2006年 05月 2006年 04月 2006年 03月 2006年 02月 2006年 01月 2005年 12月 2005年 11月 2005年 10月 2005年 09月 2005年 08月 2005年 07月 2005年 06月 2005年 05月 2005年 04月 2005年 03月 2005年 02月 2005年 01月 2004年 12月 2004年 11月 2004年 10月 2004年 09月 2004年 08月 2004年 07月 2004年 06月 2004年 05月 2004年 04月 2004年 03月 2004年 02月 2001年 01月 その他のジャンル
記事ランキング
ブログジャンル
画像一覧
フォロー中のブログ
外部リンク
|
ファン申請 |
||