2015-10-23 11 views
6

オブジェクトの構築で取得する必要があるリソースが、ローカルのコーディング標準によって禁止されている場合、RAIIを実行することはできますか?例外なくRAIIを行うことは可能ですか?

この場合、リソース取得の失敗を処理する標準的な方法は何ですか?

+1

何らかの理由で例外を使用できないときは、構築に失敗するオブジェクトの初期化メソッドを作成することになります。したがって、コンストラクタは簡単な設定以外は何もしません。次に、実際のリソース取得を行い、それに従ってtrue/falseを返すInitメソッドを持つことができます。 –

+2

あなたのガイドラインは、そのような状況については何も言いませんか?結局のところ、C++イディオムは非常に一般的なものです。ガイドラインで許可されていれば、[標準I/Oライブラリ](http://en.cppreference.com/w/cpp/io)やそのストリームと同様のシステムをいつでも使用できます。ストリームがエラーをチェックするための条件で使用できること、または 'is_open'関数を持つファイルストリームのように使用できることです。 –

+0

@JoachimPileborg私はそれがガイドラインで考慮されていたとは思わない、彼らはよく更新する必要があります(組み込みのリアルタイムシステムですが、例外は好きではありません)。この質問のために私は私の感情が確認されたいと思います! :-) – Joe

答えて

6

私はこれを悪いデザインとみなすため、一般的に無効なオブジェクトアプローチを使用しません。構築後、オブジェクトは、不変条件が成立する状態になければなりません(コンストラクタが唯一の目的である)。 がstd::vectorのようなものを実装しているとしますが、strange_vector<int>(10, 0)を呼び出した後では、割り当てが失敗したためオブジェクトは使用できなくなります。

代わりに、私はプライベートコンストラクタを宣言し、返すファクトリメソッドを使用しますオプション:例外処理の最大の利点の

class file 
{ 
public: 
    ~file() {fclose(m_file);} 

    static std::optional<file> open(std::string const& filename) 
    { 
     auto f = fopen(filename.c_str(), "r"); 
     if (f) 
     { 
      return std::make_optional<file>(f); 
     } 
     else 
     { 
      return std::nullopt; 
     } 
    } 

private: 
    file(FILE* file); 
    FILE* m_file; 
}; 

一つである(エラー処理と通常のコードパスをデカップリングに加えて)そのあなたがすることはできません誤って無視する。必要ならば、optionalのような独自のクラスを作成して、有効なオブジェクトで初期化しないとエラーメッセージを記録し、プログラム(または他の妥当なエラー処理)を終了することができます。私はtalk from A. Alexandrescu about systematic error handlingがあり、の値か例外を含むクラスExpected<T>を実装していると思います。これを基に、例外の代わりにエラー処理を追加することができます。

std::optionalはまだ標準の一部ではありませんが、最新のコンパイラの一部、追加機能、または他のライブラリのいずれかとして実装を簡単に取得できます。

+0

あなたはローカルの 'f'とメンバ' m_file'を混在させましたか? –

+0

@MatthäusBrandlはい、ありがとうございます。 – Jens

1

いつでもbool valid(void)メソッドを作成できます。コンストラクタは次に適切な条件を設定することができ、コード内では、これがうまくいくかどうかを確認することができます。

class foo 
{ 
public: 
    foo(const char *Filename) 
    { 
     mValid = false; 

     if(fopen(Filename) == NULL) 
      return; 

     mValid = true; 
    } 

    bool valid(void) { return mValid; } 

    private: 
     bool mValid; 
}; 

void myfunc(void) 
{ 
    foo fl("myfile"); 
    if(!fl.valid()) 
    { 
     printf("Error\n"); 
     return; 
    } 
} 
+0

私はこのアプローチが本当に好きではありません。ファイルを使用するfooのメソッドを呼び出すとどうなりますか?初期化は失敗しましたか?オブジェクトの不変量を確立していないコンストラクターは無駄です。 – Jens

+0

fooを使用するメソッドを呼び出す場合、ファイルが実際に有効であることを内部的に検証する必要があります。まあ、それは醜いですが、少なくともオブジェクト自体が正しく動作することを保証します。 – Devolus

+0

これは、すべてのメソッド呼び出しのチェックを追加します。私はOPが埋め込みドメインでこれを望んでいるとは確信していません。私は一般的にそれを望んでいるとは思っていません。すべてのアクセスをチェックするこのアプローチのベクタクラス... – Jens

関連する問題