我想知道为什么C ++(可能还有其他语言,我不确定)不允许这样的语句。
MyObject foo.DoBar();
你会认为语言可以理解构造对象,然后调用函数。我认为这不起作用的唯一原因是如果对象的构造失败,语句仍然会尝试调用该函数。
为什么那些帮助开发和集成新功能到C ++(可能还有其他语言)的人不允许这样做的原因是什么?
答案 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没有这个声明,可能是因为没有人想要它(当时很少有人声明具有相关功能的类型),可能是因为它可能令人困惑。计算机语言的许多功能都是出于历史目的,并且可能表明有人在几十年前做出了随机选择。这并不意味着一旦建立就没有充分理由改变它们是个好主意。
正确的问题不是“他们为什么不做这个改变?”但“他们为什么要做这个改变?”您提出的更改看起来并不真正有用,因为我可以使用两行代码执行完全相同的操作;总额外输入是一个分号,一个行尾和重复的变量名称。
缺点是它会为语言添加额外的语法,并引发返回值的问题(正如所指出的那样)。是否应该丢弃被调用函数的返回值?被叫函数是否需要返回void
或this
的某些变体?我现在能看到的任何解决方案在某些情况下都会让人感到困惑,无论C ++需要什么,都不会有更多混淆的机会。
答案 3 :(得分:0)
这里有一个问题:如果foo
需要使用非默认构造函数,该怎么办?现在是
MyObject foo(arg1, arg2).DoBar();
这有点混乱,并且确实没有比
好多少MyObject foo(arg1, arg2);
foo.DoBar();
请记住:代码应该很容易理解!
请注意,如果DoBar返回对*this
的引用,则可以执行您想要的操作:
MyObject foo = MyObject().DoBar();
使用C ++ 0x移动构造函数,这将带来很少的开销,但在此之前,预计会出现虚假副本。