2013-03-05 6 views
5

私は短い質問があります。結果としてクラスのオブジェクトを返す関数が与えられた場合、結果がない場合(たとえば、インデックスが範囲外であるため)、何を返すべきですか?私は新しい "空の"オブジェクトを返すことができましたが、成功した計算がないことをどのように指摘できますか?戻り値のある関数の結果がないことを確認する方法はありますか?

私は一般的なアプローチがあるとします。

+3

例外をスローするhttp://www.cplusplus.com/doc/tutorial/exceptions/ – Tschallacka

+3

例外をスローしますか? – PlasmaHH

+0

@MichaelDibbets。ありがとう、私は以前それを使用していなかった。あなたが短い答えとしてそれを書くなら、私はそれを受け入れられたものとしてマークします。 – danijar

答えて

2

値が期待した結果と一致しない場合は、例外をスローすることができます。

チュートリアルでは、例外はtryおよびcatch原則で動作しますhttp://www.cplusplus.com/doc/tutorial/exceptions

で見つけることができます。

プログラムは、コードを実行するには、「しようとします」。 予期しないことが起こった場合、実行されたコードはオブジェクトや変数などを「スロー」し、これが捕捉されます。 catchステートメントでは、予期せぬ事態が発生した場合に起こるべきことをコードに記述することができます。

ちょうどチュートリアルに従ってください。

+0

単に、std :: exceptionとサブクラスを投げることで、あなた自身と他の人たちの苦痛を救うことができます。これは、意味の完全なエラー文字列 'what()'を得る単一の方法を提供するからです。プレーンなint char値を投げることは、できる最悪のことです。 – josefx

+0

しかし、0xDEADまたは0xBABEを投げるのは楽しい@josefxです – Tschallacka

13

C++での一般的なアプローチは、例外をスローするかboost::optionalのようないくつかのラッパーを使用するかのいずれかです。

何らかのエラーが発生した場合は例外をスローする必要があります。空の結果を返す関数の有効な使用例であれば、boost::optional -approachが適切です。たとえば、SQLのNULLが考えられます。 boost::optionalはコードベースで非常に便利でした。可能であればvector::at法の理念で行く

+0

ちょっと最近のビデオでは、* Alexandrescu *は、「例外的な」タイプを提案しました(そのように呼ばれましたか?)。空の値であるが例外であるため、エラーの場合に使用するのが概念的に適切である(単純なboost :: optionalとは対照的に)。そうでなければ、推論+1。 –

+0

うん、見てもそれは 'Expected 'です。私がそれを言及しなかった理由は、それがまだ実験的で先進的であると考えることです。しかしそれは先進的な読者のための良いティーザーなので、ここで[リンク](http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling- in-C)。 –

3

out_of_range例外をスローします。

3

これは、操作の意味が何であるかに依存します。

エラーが発生した場合、あなたは間違いなくは例外をスローする必要があります

#include <stdexcept> // Necessary for standard exceptions 

X foo() 
{ 
    ... 
    if (/* something goes wrong... */) 
    { 
     // There may be a more appropriate exception class. You could 
     // also derive your own exception class from std::exception... 
     throw std::logic_error("Whatever!"); 
    } 

    ... 
} 

... 

try 
{ 
    X x = foo(); 
    // Work with x... 
} 
catch (std::logic_error const& e) // Catch what is appropriate... 
{ 
    std::cout << e.what(); 
} 

無値を返さないことは、エラー状態を表すものではありません場合は、Boost.Optionalを使用することができます。

std::pair<X, bool> foo(); 

... 

bool valid; 
X x; 
std::tie(x, valid) = foo(); 
if (valid) 
{ 
    // Use x... 
} 
:別の方法として、あなたはその第二の部材最初のメンバーは、以下のように有効なオブジェクトであるか否かを伝えます boolフラグであるペアを返すと考えることができ、タイプ Xの「空」のオブジェクトを作成することができます提供
+0

Boost.Optionalに言及してくれてありがとう。 – danijar

+0

'std :: pair'の解決策は、' X'型の空の値を作ることができれば意味があることに注意してください。そして、ときどき 'bool'の代わりに戻り値の空白を使うことができます。 – rodrigo

+0

@rodrigo:空のオブジェクトを返すのは好きではないが、最初の文章に同意する(ありがとう、ありがとう)。関数のシグネチャを見ると、 'pair 'はすでに ' X'は空である可能性があります。しかし、私はそれが味の問題だと思います。 –

3

誤った状況について話している場合、例外をスローすることは適切な解決策です。

#include<exception> 

Object * GenerateObject(int i) 
{ 
    if (i < 0) 
     throw std::out_of_range("i"); 

    return new Object(i); 
} 

int main(int argc, char * argv[]) 
{ 
    try 
    { 
     Object * obj = GenerateObject(-1); 

     // Succeeded 
     return 0; 
    } 
    catch (std::exception & e) 
    { 
     // Failed, exiting with error value 
     return 1; 
    } 
} 

空の値が許可されている場合は、このクラスに特定の値を指定できます。

class Rectangle 
{ 
private: 
    int left, top, width, height; 

public: 
    Rectangle(l, t, w, h) 
    { 
     left = l; 
     top = t; 
     width = w; 
     height = h; 
    } 

    public static Rectangle empty; 
} 

Rectangle Rectangle::empty = Rectangle(0, 0, -1, -1); 

// ... 

Rectangle DoSth(int i) 
{ 
    // i < 0 is NOT considered an error here 
    if (i < 0) 
      return Rectangle::empty; 

    // Further processing 
} 
+1

['std :: out_of_range'](http://en.cppreference.com/w/cpp/error/out_of_range)の例外はありませんか? – BoBTFish

+0

ここではSTLの例外に関する広範囲の知識はありません。私はそれを修正します。 – Spook

+0

サンプルコードをありがとう。 – danijar

0

戻されるオブジェクト型と列挙を組み合わせることができます。返される列挙体が特定の値である場合、オブジェクトは有効であり、そうでない場合、オブジェクトは無効な状態にある。

// This is a working C++11 example. 
#include <utility> 
#include <memory> 

enum result 
{ 
    ok, 
    out_of_range, 
    some_other_error 
}; 

class object 
{ 
    public: 
     object() {} 
}; 

typedef std::shared_ptr<object> object_ptr; 

typedef std::pair< result, object_ptr > return_type; 

return_type some_function(int index) 
{ 
    if (index > 5) 
    { 
     return return_type{ result::out_of_range, nullptr }; 
    } 

    return return_type{ result::ok, object_ptr{ new object() } }; 
} 

int main() 
{ 
    return_type res = some_function(10); 
    if (res.first == result::ok) 
    { 
     // Do something with res.second 
    } 
    else 
    { 
     // Handle the error 
    } 
} 

私はたぶん例外をスローします。

関連する問題