我喜欢Python中的功能,当它找不到正确的返回值时可以返回None。例如:
def get(self, key):
if key in self.db:
return self.db[key]
return None
我需要在C ++中实现相同的功能。我想到了一些可能性。
bool get(string key, int& result)
{
if (in(key, db)) {
result = db[key];
return true;
}
return false;
}
int get(string key) throw (int)
{
if (in(key, db)) {
result = db[key];
return result;
}
throw 0;
}
try {
....
}
catch (int n)
{
cout << "None";
}
pair<bool, int> getp(int i)
{
if (...) {
return pair<bool, int>(true, 10);
}
return pair<bool,int>(false, 20);
}
pair<bool, int> res = getp(10);
if (res.first) {
cout << res.second;
}
C ++中通常使用哪一个?有没有其他方法可以用C ++做到这一点?
答案 0 :(得分:15)
执行此操作的常规C ++方法(注意:C ++不是Python)是从这些函数返回迭代器,并在找不到该项时返回end()
。
如果您希望使用非迭代器返回值,请使用boost::optional
并在返回Python boost::none
时返回None
。
绝对不要使用throw
,除非您希望从不在正常执行期间出现错误案例。
答案 1 :(得分:3)
我使用一个小的自定义Checked
模板类来实现好/坏返回值。
我的实际课程更全面,包括赋值运算符,错误原因字符串和引用类型的特化等等,这就是我没有使用boost::optional<T>
的原因。如果有兴趣,我可以发表全班。
班级的一般要点是:
static const class Bad {} None;
template<typename ValueType>
class Checked
{
public:
// Constructor for good value.
Checked(ValueType x)
: value(x), valid(true)
{}
// Constructor for bad value.
Checked(Bad)
: value(), valid(false)
{}
operator ValueType(void) const
{
if (!valid)
;//assert or throw...
return value;
}
ValueType value;
bool valid;
};
这可以这样使用:
Checked<int> Divide(int numerator, int denominator)
{
if (denominator == 0)
return Bad(); // or None;
return numerator / denominator; // Automatically uses the "good value" constructor
}
或:
Checked<int> result = Divide(4, 5);
if (result.valid)
std::cout << result; // or result.value
else
std::cout << "Bad!";
由于返回值优化,这种方法通常比参考方法更有效。
答案 2 :(得分:1)
我认为C ++中的不同项目使用不同的标准,但你提到的返回true / false 可能是C ++中最常见的方式,虽然有些人喜欢在成功时返回false而其他人则返回true成功。在其他情况下,如果你想获得的值是一个指针,那么返回null是C ++中另一种常见的方式。
例如,如果您正在处理与Microsoft相关的项目,那么最常见的方法是返回HRESULT,这是Microsoft引入的返回类型。
在linux中,函数通常在成功时返回0,非零值表示错误代码。 (您可能会发现this discussion有帮助。)
答案 3 :(得分:1)
我想说这三种方法在C ++中都很常见。
不言而喻,如果返回类型已经具有某种“无效”或“僵尸”状态(例如,像NULL
指针或NaN
数字),则可能只是最容易使用的东西。
“通过引用获取输出参数并返回错误代码”是更传统的C风格的处理方式,这当然是非常常见的。传统是在成功时返回0,在失败时返回一些错误代码(任何非零值)。
如果在代码中采用异常,那么“如果无法返回值则抛出异常”通常是有意义的。这是非常常见的,但并非普遍接受(并非所有人都喜欢或使用例外用于相同目的)。
前两个选项是永无止境的不和(即错误代码与异常),它实际上取决于你选择哪一方。所以,我想请你参考那个辩论(当然,这对于StackOverflow来说太主观了。)
我想说,“返回一对bool
和价值”并不常见,但我仍然多次见过这种情况。通过使用元组(boost::tuple
或std::tuple
(C ++ 11))并使用层(boost::tie
或std::tie
(C ++ 11)),从函数中返回多个值的整个想法(如许多语言所允许的)在实践中更具吸引力和使用。
在其他选项中,您有boost::optional<T>
,其名称非常明显(基本上,第三个选项(对)包装在更漂亮的包中)。你可能还有Alexandrescu的预期模板,它为你提供了所有三个选项的混合,这样你就可以获得一个带有标志的返回值,以确定它是否有效,并捆绑了一个描述无法生成的原因的异常。该值,如果您尝试读取无效值,将自动抛出该值。但是,该模板需要C ++ 11功能才能工作。
答案 4 :(得分:1)
返回指针时,我可以使用reinterpret_cast返回NULL。
class A
{
};
A* a(int i)
{
if (i == 0) return new A();
return reinterpret_cast<A*>(NULL);
}
int main(int argc, char *argv[]) {
A* result = a(1); // result is NULL
if (result == NULL) {
cout << "NULL returned";
}
result = a(0);
if (result != NULL) {
cout << "NON NULL returned";
}
}