私は短い質問があります。結果としてクラスのオブジェクトを返す関数が与えられた場合、結果がない場合(たとえば、インデックスが範囲外であるため)、何を返すべきですか?私は新しい "空の"オブジェクトを返すことができましたが、成功した計算がないことをどのように指摘できますか?戻り値のある関数の結果がないことを確認する方法はありますか?
私は一般的なアプローチがあるとします。
私は短い質問があります。結果としてクラスのオブジェクトを返す関数が与えられた場合、結果がない場合(たとえば、インデックスが範囲外であるため)、何を返すべきですか?私は新しい "空の"オブジェクトを返すことができましたが、成功した計算がないことをどのように指摘できますか?戻り値のある関数の結果がないことを確認する方法はありますか?
私は一般的なアプローチがあるとします。
値が期待した結果と一致しない場合は、例外をスローすることができます。
チュートリアルでは、例外はtryおよびcatch原則で動作しますhttp://www.cplusplus.com/doc/tutorial/exceptions
で見つけることができます。
プログラムは、コードを実行するには、「しようとします」。 予期しないことが起こった場合、実行されたコードはオブジェクトや変数などを「スロー」し、これが捕捉されます。 catchステートメントでは、予期せぬ事態が発生した場合に起こるべきことをコードに記述することができます。
ちょうどチュートリアルに従ってください。
単に、std :: exceptionとサブクラスを投げることで、あなた自身と他の人たちの苦痛を救うことができます。これは、意味の完全なエラー文字列 'what()'を得る単一の方法を提供するからです。プレーンなint char値を投げることは、できる最悪のことです。 – josefx
しかし、0xDEADまたは0xBABEを投げるのは楽しい@josefxです – Tschallacka
C++での一般的なアプローチは、例外をスローするかboost::optional
のようないくつかのラッパーを使用するかのいずれかです。
何らかのエラーが発生した場合は例外をスローする必要があります。空の結果を返す関数の有効な使用例であれば、boost::optional
-approachが適切です。たとえば、SQLのNULLが考えられます。 boost::optional
はコードベースで非常に便利でした。可能であればvector::at法の理念で行く
ちょっと最近のビデオでは、* Alexandrescu *は、「例外的な」タイプを提案しました(そのように呼ばれましたか?)。空の値であるが例外であるため、エラーの場合に使用するのが概念的に適切である(単純なboost :: optionalとは対照的に)。そうでなければ、推論+1。 –
うん、見てもそれは 'Expected
はout_of_range
例外をスローします。
これは、操作の意味が何であるかに依存します。
エラーが発生した場合、あなたは間違いなくは例外をスローする必要があります
#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
の「空」のオブジェクトを作成することができます提供
誤った状況について話している場合、例外をスローすることは適切な解決策です。
#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
}
戻されるオブジェクト型と列挙を組み合わせることができます。返される列挙体が特定の値である場合、オブジェクトは有効であり、そうでない場合、オブジェクトは無効な状態にある。
// 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
}
}
私はたぶん例外をスローします。
例外をスローするhttp://www.cplusplus.com/doc/tutorial/exceptions/ – Tschallacka
例外をスローしますか? – PlasmaHH
@MichaelDibbets。ありがとう、私は以前それを使用していなかった。あなたが短い答えとしてそれを書くなら、私はそれを受け入れられたものとしてマークします。 – danijar