2011-09-12 4 views
2

私は以前のCスタイルのコードのいくつかをリファクタリングして、C++コードをもっと整えるよう取り組んでいます。私はまだC++コンストラクタはエラーをどのように報告する必要がありますか?外部フラグへのポインタ?

私が働いているコードの例に少し新しいです、私はクラスの開発を考えていた

Errmsg foo{ 
    ErrMsg err = NoError; 
    /* 
    Some Processing 
    */ 
    err = foo_cleanup(err,/* some parameters*/); 
    /* 
    Some More Processing 
    */ 
    return err; 
} 

を次のようにあるので、

class foo_class 
{ 
public: 
    foo_class(Errmsg errmsg_init&,/*Some other arguments */): 
     errmsg(&errmsg_init), 
     /*Initialize other parameters */{} 

    void foo_cleanup (/*Other parameters*/); 
    // same functionality, but since the source variable is available, 
    // it can be modified without having to return any variable 

    ~foo_class(){foo_cleanup(/*Parameters*/);} 

    /* 
    Member functions 
    */ 

private: 
    Errmsg* errmsg; 
    /*Some other parameters */ 
}; 

Errmsg foo{ 
    ErrMsg err = NoError; 
    foo_class foo_obj(err); 
    /* 
    Some Processing 
    */ 

    // The class would be 
    //cleaned up before returning 
    // and the err variable would be 
    //modified in the destructor 
    return err; 
} 

私が持っているが、このアプローチに類似したものを使用することができましたが、これが移植可能かどうかはわかりません。

これは正しいことですか?

もしそうでなければ、エラーメッセージ変数を参照渡しする代わりにポインタを使ってクラスを初期化するだけですか?それとも他に何かできますか?

「戻りエラーメッセージ」アプローチを使用する外部コードへの/からの関数呼び出しが多数あるため、現在の段階で例外を使用することはできません。

答えて

1

struct foo_class { 
    foo_class() { } // default constructor cannot fail 
    Errmsg nothrow_init(/* other params */) throw() { 
     /* initialize other parameters */ 
    } 
    foo_class(/* other params */) { 
     if (nothrow_init(/* other params */) != ERRMSG_OK) { 
      throw something; 
     } 
    } 
}; 

、例外-使用したコードは、マルチを呼び出すことができます例外を回避するコードはデフォルトのコンストラクタを呼び出してnothrow_initを呼び出すことができます(そして、nothrow_initが失敗した場合、使用できないオブジェクトを手に持つことになります)。彼らはそれを使用しないようにするのは彼らの責任です)。

将来、コードベースの他の部分を例外使用状態にすると、initのコードは、それ自体がスローできるものを呼び出すことがわかります。その時点で、コードを動かすことができるので、nothrow_initinit関数を呼び出すことができますが、例外をキャッチしてエラーコードに変換します。内部クラスだと仮定すると、最終的にはnothrow_initは使用されず、削除することはできます。

0

多く 機能があるので、私は現在の段階で例外を使用することはできません、まだ「リターンエラー メッセージ」のアプローチを使用して外部コードから/への呼び出し。

まず、この問題を解決してください。その後、例外を使用します。それはこのような悪いユースケースを許可するため

+0

-1 ...非常に多くのものがあります。例外はツールです。すべてを無視して、あなたの信念を打ち砕くと言って、どのようにプログラムするべきかは別のものです。 1つの文の応答はめったに役に立ちません。制御フローとしての例外?あなたの推理を広げてください。私はそれを投票し、私が間違っていたと言っています。 –

+0

私の答えとリンクされたGOTWを参照してください。例外はすべての状況に適しているわけではありませんが、そのような状況では***有効な代替手段はありません。失敗したオブジェクトの構築はそれらの1つです。 – spraff

+0

フロー制御がより適しているコンストラクタでは、なにもしないでください。時には、この種のことを行うために完全に有効です。これは明らかではありません。チャンスがあれば、本当にあなたはCHeyWeJustAddedANumberExceptionをスローします:P –

1

あなたのコードは危険です:

return new FooClass (local_error_code_variable); 

は、リターンコードをコンストラクタの失敗を通知しようとしないでください。 できません。例外を使用します。

例外をリターンコードでラップすることも、その逆も可能です。

class NewAPIClass { 
    NewAPIClass() { 
     error_code err = old_api_function(); 
     if (OLD_API_OK != err) 
      throw NewAPIException (err); 
    } 
} 

extern "C" error_code new_api_callback_function (argument arg) { 
    try { 
     NewAPIClass object; 
     object .do_work(); 
    } 
    catch (...) { 
     return OLD_API_ERROR; 
    } 
} 

int main() { 
    old_api_install_callback (new_api_callback_function); 
} 

例外は重要です。 GOTW articlesがたくさんあり、C++開発者としての目標を理解する必要があります。

例外を正しく使用するための新しいコードを記述してください。古いコードと新しいコードとの間の境界線にヒットするたびにエラータイプを変換します。

ところで、例外はコンストラクタが失敗するのみ合理的な方法です。これは、C++を非常に強力にするための鍵となるRAIIの一部です。コンストラクタはあなたのインバリアントを確立し、例外は事後条件を満たすことができないというシグナルを出します - すべてまとめてここに重要な哲学です:C++の有効なオブジェクトのみが存在する必要があります、RAIIを悪用してこの権利を取得すれば、オブジェクトはプログラムの妥当性の証です。例外はOKである、あなたは、二期工事のイディオムを使用することができるように、あなたは、可能な場合は、呼び出し元のコードを修正する必要があることはともかく

関連する問題