为什么C ++不在同一行中实现构造+调用函数?

时间:2010-01-20 04:52:49

标签: c++

我想知道为什么C ++(可能还有其他语言,我不确定)不允许这样的语句。

MyObject foo.DoBar();

你会认为语言可以理解构造对象,然后调用函数。我认为这不起作用的唯一原因是如果对象的构造失败,语句仍然会尝试调用该函数。

为什么那些帮助开发和集成新功能到C ++(可能还有其他语言)的人不允许这样做的原因是什么?

4 个答案:

答案 0 :(得分:13)

可以构造一个对象并立即调用它上面的函数,如果你这样做就不能将对象赋值给变量:

MyObject().DoBar();

这种限制的一个实际原因是构造函数创建了对象,并且您正在调用的函数也可能具有返回值,因此您最终会得到同一语句生成的两个值。然后你需要一些特殊的语法来将这两个值分配给变量,这在其他任何地方都不会发生。

通过直接调用该方法可能获得的一点点便利并没有那么大的优势,值得为它引入新的语法。

答案 1 :(得分:3)

我认为更好的问题是为什么要这样?毕竟:

MyObject foo;
foo.DoBar();

几乎没有困难。它也更具可读性(虽然显然可能有偏见。)即使你可以构建调用,它也可能被标记为“坏事”。排序如何允许同一行上的多个声明,但通常会降低可读性。

这种结构为已经很复杂的语言增加了规则和复杂性,当一个可以说是优选的解决方案已经存在时。我们真的想为一种语言添加昂贵的糖来节省一些按键吗?

回应:

  

“虽然你想构建一个对象并且只需要调用一个函数,但我可以看到它很有用。”

如果你想构建一个只是为了调用一个函数的对象,是否可以只使该函数成为一个自由函数?毕竟,无论如何,它都在默认数据或传递给构造函数的数据上运行。唯一缺少的就是析构函数。

更不用说其他选项了:

struct MyObject
{
    MyObject(bool pCallDoBar = true)
    {
        if (pCallDoBar)
            DoBar();
    }

    void DoBar(void)
    {
    }
};

MyObject foo;

或者只是:

MyObject().DoBar(); // destructor called here, though

我认为你需要一个具体的例子才能真正说明问题。

答案 2 :(得分:2)

在上一段中,您指的是C ++标准委员会。由于委员会用完了时间(例如当前标准中的std::unordered_map和即将发布的概念中的概念),因此繁忙,并且重要的语言功能会被删除。没有充分理由,他们对进行微小改动不感兴趣。在标准委员会召开前几天,Bjarne Stroustrup对于添加次要功能并不感兴趣。

C没有这个声明,可能是因为没有人想要它(当时很少有人声明具有相关功能的类型),可能是因为它可能令人困惑。计算机语言的许多功能都是出于历史目的,并且可能表明有人在几十年前做出了随机选择。这并不意味着一旦建立就没有充分理由改变它们是个好主意。

正确的问题不是“他们为什么不做这个改变?”但“他们为什么要做这个改变?”您提出的更改看起来并不真正有用,因为我可以使用两行代码执行完全相同的操作;总额外输入是一个分号,一个行尾和重复的变量名称。

缺点是它会为语言添加额外的语法,并引发返回值的问题(正如所指出的那样)。是否应该丢弃被调用函数的返回值?被叫函数是否需要返回voidthis的某些变体?我现在能看到的任何解决方案在某些情况下都会让人感到困惑,无论C ++需要什么,都不会有更多混淆的机会。

答案 3 :(得分:0)

这里有一个问题:如果foo需要使用非默认构造函数,该怎么办?现在是

MyObject foo(arg1, arg2).DoBar();

这有点混乱,并且确实没有比

好多少
MyObject foo(arg1, arg2);
foo.DoBar();

请记住:代码应该很容易理解!

请注意,如果DoBar返回对*this的引用,则可以执行您想要的操作:

MyObject foo = MyObject().DoBar();

使用C ++ 0x移动构造函数,这将带来很少的开销,但在此之前,预计会出现虚假副本。