Python的无返回功能模仿C ++

时间:2013-06-13 22:58:30

标签: c++ return

我喜欢Python中的功能,当它找不到正确的返回值时可以返回None。例如:

def get(self, key):
    if key in self.db:
        return self.db[key]
    return None

我需要在C ++中实现相同的功能。我想到了一些可能性。

返回true / false,当true从引用或指针

获取值时
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 ++做到这一点?

5 个答案:

答案 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::tuplestd::tuple(C ++ 11))并使用层(boost::tiestd::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";
    }
}