短い質問があります。結果としてクラスのオブジェクトを返す関数がある場合、結果がない場合(たとえば、インデックスが範囲外であるため)、何を返す必要がありますか?新しい「空の」オブジェクトを返すことはできますが、計算が成功しなかったことをどのように指摘できますか?
一般的なアプローチがあると思います。
短い質問があります。結果としてクラスのオブジェクトを返す関数がある場合、結果がない場合(たとえば、インデックスが範囲外であるため)、何を返す必要がありますか?新しい「空の」オブジェクトを返すことはできますが、計算が成功しなかったことをどのように指摘できますか?
一般的なアプローチがあると思います。
C ++での一般的なアプローチは、例外をスローするか、のようなラッパーを使用することboost::optional
です。
ある種のエラーの場合は例外をスローする必要がboost::optional
あります。空の結果を返す関数の有効なユースケースである場合は、-approachの方が適切です。頭に浮かぶ1つの例は、SQLのNULLです。boost::optional
私たちのコードベースでは非常に便利であることがわかりました。
vector :: atメソッドの哲学に従って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を使用できます。または、タイプの「空の」オブジェクトを作成できる場合は、次のように、最初のメンバーが有効なオブジェクトであるかどうかをX
示すフラグである2番目のメンバーを持つペアを返すことを考えることができます。bool
std::pair<X, bool> foo();
...
bool valid;
X x;
std::tie(x, valid) = foo();
if (valid)
{
// Use 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
}
値が期待される結果と一致しない場合は、例外をスローできます。
チュートリアルはhttp://www.cplusplus.com/doc/tutorial/exceptionsにあります。
例外は、tryandcatchの原則で機能します。
プログラムはコードの実行を「試行」します。予期しないことが起こった場合、実行されたコードはオブジェクトや変数などを「スロー」し、これがキャッチされます。catchステートメントでは、予期しないことが起こった場合に何が起こるかをコードに含めることができます。
チュートリアルに従ってください。
列挙型と返されるオブジェクト型を組み合わせることができます。返された列挙が特定の値である場合、オブジェクトは有効です。そうでない場合、オブジェクトは無効な状態になります。
// 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
}
}
代わりに、おそらく例外をスローします。