当他在容器中请求边界之外的元素时,如何将无效对象返回给用户。我不会抛出异常。
我编写了自己的模板哈希表
template <class Type1, class Type2> class wqHashTable
{
public:
template <class Type1, class Type2>
Type2& wqHashTable<Type1, Type2>::operator[](int idx) const
{
if (goodId(idx))
{
return m_pValue[idx];
}
else
{
Type2* tValue = new Type2[1]; //TODO: How do we handle errors?
return tValue[0];
}
}
}
答案 0 :(得分:2)
如果您不喜欢异常(出于任何不明原因,您应该在这里使用它们),请尝试Boost.Optional。
boost::optional<Type2&> operator[](int idx) const
{
if(good_idx(idx)
return boost::optional<Type2&>(m_pValue[idx]);
return boost::optional<Type2&>(); // uninitialized
}
致电代码:
boost::optional<the_type&> opt_ret = your_table[idx];
if(ret){
the_type& ret = *opt_ret; // for convenience
// valid idx, use ret
}
或者你可以按照std::vector
的设计,只返回m_pValue[idx]
,无论好坏,并提供一个.at(int idx)
方法进行边界检查(并抛出异常,如果检查失败)。
总而言之,没有理由不使用例外。其他答案已经详细说明了。
答案 1 :(得分:1)
throw
(IDK为什么你不想这样做)或。return NULL;
另一种选择是在返回的类型中使用像“.thisIsErrorObject”这样的字段;这样,您可以构造自己的错误代码对象。
答案 2 :(得分:1)
我建议抛出异常,因为其他任何东西都会使用户代码中的控制流程复杂化(或被忽略并导致意外结果)。如果有一个迫切的理由不使用异常,那么下一件事就是实现Null对象模式(即有一个静态的 null 对象,当你无法返回一个真实的对象时,它会返回给用户的引用)。
在这种特殊情况下Null对象模式的问题在于,除非您创建单独的派生类型(繁琐,不是容器的角色,但可能适合应用程序的更大设计),否则该对象将无法与任何有效对象区分开来对象,你将强迫用户检查引用绑定的对象的地址,这意味着你回来了返回一个指针(可以自己为空,不需要提供Null对象)。
答案 3 :(得分:0)
如果您不想抛出异常,则需要知道自己想要做什么。例如,您可能希望有一个预定义的成员在超出边界的情况下返回引用。我认为你不想在这里new
做任何事情,但话又取决于你的意图。
答案 4 :(得分:0)
我会assert(goodId(idx));
和return m_pValue[idx];
。
有点奇怪,用户应该如何知道存储中的索引。如果它是供内部使用的东西,断言可能是绝对足够的。
否则,也许使用标准关联容器的设计?
答案 5 :(得分:0)
template <class Type1, class Type2> class wqHashTable
{
Type2 INVALID_ELEMENT;
public:
bool last_access_valid;
template <class Type1, class Type2>
Type2& wqHashTable<Type1, Type2>::operator[](int idx) const
{
last_access_valid = goodId(idx);
if (last_access_valid )
return m_pValue[idx];
else
return INVALID_ELEMENT;
}
}
这需要Type2
作为默认构造,这不是你将永远保证的,但它很常见。来电者可以查看last_access_valid
。
如果您打算使用这样的last_access_valid
这样的话,我强烈建议我在https://stackoverflow.com/a/8088357/845092张贴一个类来保证每次都检查它,这样你就不会意外忘记。在这种情况下,last_access_valid
的类型为ForceCheckError<bool>
,如果调用者未检查,则assert
。