23

看看这些函数签名:

 class Number {
 public:
   Number& operator++ ();    // prefix ++
   Number  operator++ (int); // postfix ++
 }; 

Prefix 不带任何参数,但 postfix 可以。为什么?我想我们可以用不同的返回类型来识别它们。

4

6 回答 6

11

前缀和后缀++是不同的运算符。使用标准Foo operator symbol(Foo &)样式声明,没有明显的方法可以区分两者。语言设计者想要一些其他的解决方案,而不是想出一些新的语法Foo symbol operator(Foo &),比如让它成为与所有其他运算符不同的特殊情况,并且可能有点难以解析。

他们选择的解决方案有些奇怪。他们指出,所有其他“后缀”运算符(即出现在其操作数之一之后的运算符)实际上都是带有两个参数的中缀运算符。例如,普通的+old/>. 在此基础上,语言设计者决定使用随机伪参数是区分前缀和后缀的好方法++

恕我直言,这是随着 C++ 的发展而做出的奇怪决定之一。但是你现在有了。

您无法根据返回类型区分它们,原因有两个。

首先是 C++ 中的函数不能在返回类型上重载。您不能有两个具有相同名称和参数类型列表但返回值不同的函数。

第二个是该方法不够健壮或不够灵活,无法处理 prefix 和 postfix 的所有可能实现++

例如,++如果您调用它的唯一原因是调用与您应用它的变量的值无关的副作用,您可能想要一个返回引用类型的后缀。在我看来,这将是一个非常糟糕的实现,但 C++ 并不是要判断你想编写什么样的愚蠢代码,而是让你能够编写你认为适合这种情况的任何代码。并且强迫您对前缀++和后缀使用一种特定样式的返回类型++将与这种精神背道而驰。

于 2010-08-26T12:20:24.150 回答
10

你可以自由地给 operator++ 任何你喜欢的返回类型,所以没有办法区分后缀和前缀。所以编译器需要某种线索。

OTOH,我不知道为什么这不能仅在语法中完成:

//prefix
int& ++operator (); 
//postfix
int& operator++ (); 

毕竟,在声明中模仿用法在 C 和 C++ 中具有传统。

PS 其他海报:这与返回类型的重载无关。后缀和前缀 ++/-- 是两个不同的名称。没有必要解决x++or中的重载++x,因为完全清楚意味着哪个名称。

于 2010-08-26T12:00:30.097 回答
7

直接来自 Bjarne 的嘴:

这可能太可爱也太微妙了,但它确实有效,不需要新的语法,并且有一个疯狂的逻辑。其他一元运算符是前缀并且在定义为成员函数时不带参数。“奇数”和未使用int的虚拟参数用于指示奇数后缀运算符。换句话说,在后缀的情况下,++位于第一个(实)操作数和第二个(虚拟)参数之间,因此是后缀。

这些解释是必要的,因为该机制是独一无二的,因此有点棘手。如果可以选择,我可能会引入prefixandpostfix关键字,但当时这似乎不可行。但是,唯一真正重要的一点是该机制有效,并且可以被真正需要它的少数程序员理解和使用。

顺便说一句,在我看来,++程序员应该只重载前缀,而后缀++应该由编译器自动生成。有人同意我的观点吗?

于 2010-08-26T14:48:58.113 回答
2

不允许纯粹通过返回类型重载函数,因此需要一个虚拟参数来区分两个外观相同的operator++()运算符。

于 2010-08-26T12:00:48.070 回答
0

如果我有我的 druthers,后增量和许多序列点运算符将被分成两三个部分;在后增量的情况下,像“a=(b++ + c++);”这样的语句 将有效地翻译为“a=postinc1(b)+postinc1(c); postinc2(b); postinc2(c);”;后增量的第二部分将是一个 void 函数。在实际实现中, postinc2() 调用应该经常发生,而其他一些结果位于评估堆栈上;这对于编译器来说应该不会太难实现。

在“&&”或“||”的情况下,运算符的第一部分将只对左操作数进行操作;如果它返回非零(对于 &&)或非零(对于 ||),那么第二部分将对两个操作数进行操作。

在 "?"/":" 的情况下,运算符的第一部分将仅对第一个操作数进行操作。如果它返回非零,则第二部分将对第一个和第二个参数进行操作;否则第三部分将对第一个和第三个参数进行操作。

有任何语言做这样的事情吗?C++ 允许以破坏排序行为的方式重新定义运算符,但不允许以保留顺序行为的方式重新定义它们,这似乎很奇怪。

于 2010-09-16T23:04:36.990 回答
0

编译器使用 int 参数来区分前缀和后缀增量运算符。对于隐式调用,默认值为零,因此实际上它对重载运算符的功能没有太大影响......

于 2013-11-23T06:36:08.433 回答