5

短い質問があります。結果としてクラスのオブジェクトを返す関数がある場合、結果がない場合(たとえば、インデックスが範囲外であるため)、何を返す必要がありますか?新しい「空の」オブジェクトを返すことはできますが、計算が成功しなかったことをどのように指摘できますか?

一般的なアプローチがあると思います。

4

6 に答える 6

13

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

ある種のエラーの場合は例外をスローする必要がboost::optionalあります。空の結果を返す関数の有効なユースケースである場合は、-approachの方が適切です。頭に浮かぶ1つの例は、SQLのNULLです。boost::optional私たちのコードベースでは非常に便利であることがわかりました。

于 2013-03-05T10:38:36.500 に答える
3

vector :: atメソッドの哲学に従ってout_of_range、可能であれば例外をスローします。

于 2013-03-05T10:38:38.170 に答える
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を使用できます。または、タイプの「空の」オブジェクトを作成できる場合は、次のように、最初のメンバーが有効なオブジェクトであるかどうかをX示すフラグである2番目のメンバーを持つペアを返すことを考えることができます。bool

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

...

bool valid;
X x;
std::tie(x, valid) = foo();
if (valid)
{
    // Use x...
}
于 2013-03-05T10:40:46.357 に答える
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
}
于 2013-03-05T10:40:54.230 に答える
2

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

チュートリアルはhttp://www.cplusplus.com/doc/tutorial/exceptionsにあります。

例外は、tryandcatchの原則で機能します。

プログラムはコードの実行を「試行」します。予期しないことが起こった場合、実行されたコードはオブジェクトや変数などを「スロー」し、これがキャッチされます。catchステートメントでは、予期しないことが起こった場合に何が起こるかをコードに含めることができます。

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

于 2013-03-05T10:44:36.823 に答える
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
    }
}

代わりに、おそらく例外をスローします。

于 2013-03-05T22:07:23.753 に答える