我有以下类型:
typedef QPair < QTime , QTime > CalculatedTimeSlotRange;
typedef QList < CalculatedTimeSlotRange > CalculatedTimeSlotRangeList;
typedef QHash < quint8 , CalculatedTimeSlotRangeList > TimeSlotsTable;
我有以下功能:
const CalculatedTimeSlotRangeList* TimeSlots::getCalculatedTimeSlotRangeList(const quint8 id) const
{
QHashIterator<quint8,CalculatedTimeSlotRangeList> it(mTimeSlotsTable);
while (it.hasNext()) {
it.next();
if(it.key() == id) {
return &it.value();
}
}
return NULL;
}
正如您所看到的,如果找不到与NULL
匹配的密钥,我的函数将返回id
。它是否正确?或者如果密钥不存在,我应该抛出异常吗?我应该如何为这种情况抛出异常?
修改
在看到评论和答案后,我认为重要的是要指出抛出异常或返回null无关紧要。此事件意味着通过许多文件提供给程序的参数不正确。程序必须显示错误消息,并要求用户将参数文件替换为正确的参数文件。那么这里更好的选择是什么?异常或空指针,因为它们在这个上下文中意味着相同的东西。如果不能反映我的实际意图,请编辑问题和描述。
答案 0 :(得分:1)
问问自己:如果你是某人使用这个功能,你更喜欢哪种行为?这两个选项中的每一个都有其优点和缺点 - 如果你抛出一个异常,那么onus是在调用代码上知道这种可能性并在某个时候捕获异常,否则程序将中止(),用户看起来几乎和崩溃一样。
另一方面,如果您的函数返回NULL,那么调用程序上的onus将在继续之前检查返回的NULL-ness值,否则由于NULL指针取消引用而导致程序崩溃的风险。此外,处理返回指向对象的指针的函数可能会在对象所有权问题上造成混淆 - 调用者必须问自己,&#34;我应该删除此对象,当我&#39;用它完成了吗?&#34; - 得到错误的答案将导致崩溃或内存泄漏。
您还可能没有考虑过第三个选项:返回对虚拟对象的引用。使用该选项实现该功能可能如下所示:
const CalculatedTimeSlotRangeList & TimeSlots::getCalculatedTimeSlotRangeList(const quint8 id) const
{
QHashIterator<quint8,CalculatedTimeSlotRangeList> it(mTimeSlotsTable);
while (it.hasNext()) {
it.next();
if(it.key() == id) {
return it.value();
}
}
static const CalculatedTimeSlotRangeList _dummyObject; // note: static to avoid dangling reference when returned!
return _dummyObject;
}
我喜欢这种方法,因为现在用户不必担心检查NULL,和他也不必担心正确处理异常。此函数将始终返回对有效CalculatedTimeSlotRangeList的引用;在未找到的情况下,它将是一个空的/默认构造的; (取决于您的特定用例)可能是完全可以接受的。
答案 1 :(得分:0)
由于失败条件表明程序配置存在致命错误,因此在您建议的选项中,我肯定会建议抛出异常,因为这是一个非常特殊的情况。
我认为invalid_argument
在这里有意义,所以你会#include <stdexcept>
然后用return
替换你的throw std::invalid_argument("your error message about the bad configuration");
语句