传递无效参数时函数应该返回什么?

时间:2013-10-09 17:43:56

标签: c++

我想知道当参数不符合if条件时,这个get函数应该返回什么

    template <class Object>
    const Object& SparseMat<Object>::get(int c, int r) //const
    {
        if((c >= 0)&&(c <= cCapacity)&&(r >= 0)&&(r <= rCapacity))
        {
            return mObjects[c][r];
        }
        //what should I return here?
    }

3 个答案:

答案 0 :(得分:11)

你应该抛出异常:

#include <stdexcept>

throw std::out_of_range("Indexes are out of range");

答案 1 :(得分:4)

您实际上有多种选择,特别是如果您愿意更改签名。

最有可能的是,您希望发出错误信号,而异常在这里非常有趣:

template <class Object>
const Object& SparseMat<Object>::get(int c, int r) const
{
    if((c >= 0)&&(c <= cCapacity)&&(r >= 0)&&(r <= rCapacity))
    {
        return mObjects[c][r];
    }
    throw UnknownCoordinates(c, r, cCapacity, rCapacity);
}

或者,更改签名,您可以包含无效的概念:

template <class Object>
Object const* SparseMat<Object>::get(int c, int r) const
{
    if((c >= 0)&&(c <= cCapacity)&&(r >= 0)&&(r <= rCapacity))
    {
        return &mObjects[c][r];
    }
    return nullptr;
}

使用boost::optional

可以更明确地说明这一点
template <class Object>
boost::optional<Object const&> SparseMat<Object>::get(int c, int r) const
{
    if((c >= 0)&&(c <= cCapacity)&&(r >= 0)&&(r <= rCapacity))
    {
        return mObjects[c][r];
    }
    return boost::none;
}

或者,在不更改签名的情况下,您可能希望使用null对象,但这几乎不是最佳选择(它将您限制为嵌入无效概念的对象,并且此类对象更好地重构为不具有无效性概念而是依赖于boost::optional<Object>

template <class Object>
const Object& SparseMat<Object>::get(int c, int r) const
{
    if((c >= 0)&&(c <= cCapacity)&&(r >= 0)&&(r <= rCapacity))
    {
        return mObjects[c][r];
    }
    return null; // where null is "static Object const null;" for example.
}

答案 2 :(得分:0)

完全取决于你决定它应该返回什么以及它是否应该返回。也许不是返回它应该中止(“崩溃”)或抛出异常?正如其他答案已经提出的那样,抛出异常可能就是这种情况下的嵌套方法。

但是,如果你真的坚持返回某些东西以回应错误的输入,那么在这种情况下你有一个选择就是预定义的“虚拟”/“监护人”类型的对象Object专门用于处理此类情况。

template <class Object>
class SparseMat 
{
  ...
  static Object error_object;
};


template <class Object>
const Object& SparseMat<Object>::get(int c, int r) //const
{
    if((c >= 0)&&(c <= cCapacity)&&(r >= 0)&&(r <= rCapacity))
    {
        return mObjects[c][r];
    }

    return error_object;
}

根据设计的不同,您可能希望通过调用代码轻松识别error_object。或者你可以设计那个“监护人”对象,这样调用代码就能正常工作,甚至不会意识到返回的对象是“虚拟”。再次,由你决定。