为什么后缀增量运算符采用伪参数?

Nar*_*uto 20 c++ language-design operator-overloading prefix postfix-operator

看看这些功能签名:

 class Number {
 public:
   Number& operator++ ();    // prefix ++
   Number  operator++ (int); // postfix ++
 }; 
Run Code Online (Sandbox Code Playgroud)

前缀不带任何参数,但后缀确实如此.为什么?我认为我们可以用不同的返回类型识别它们.

Omn*_*ous 10

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

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

恕我直言,这是C++发展过程中做出的陌生决定之一.但是你现在有了.

并且由于两个原因,您无法根据返回类型区分它们.

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

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

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

  • 作为旁注,我从Bjarne Stroustroup的"C++的设计和演变"中收集了这些信息.如果你想真正理解为什么C++会这样,我会推荐它.在向后兼容性非常重要的环境中通过增长来增长语言会导致很多奇怪的事情. (3认同)
  • @Mike:您不必将`post_increment`作为新关键字.如果为"显式"运算符名称引入新语法,则可以添加如下规则:`'operator''explicit'<identifier>(<args>)`其中identifier必须是显式运算符名称之一(如' post_increment','pre_increment'等).从解析的角度来看,它们不一定是保留字,因为它们在"operator explicit"位置只是"特殊".这很容易实现! (2认同)

Nor*_*ame 8

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

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

//prefix
int& ++operator (); 
//postfix
int& operator++ (); 
Run Code Online (Sandbox Code Playgroud)

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

PS其他海报:这与返回类型的重载无关.后缀和前缀++/ - 是两个不同的名称.没有必要解决重载,x++或者++x因为它完全清楚是什么名称.

  • @Shadow:postfix的额外参数用作视觉提醒,表示动作发生在右侧. (2认同)
  • 重载不能作为`++ operator`来完成,因为那样,为了保持一致,你必须制作所有标准的一元运算符(+, - ,!,*,〜)前缀表示法,然后是`*运算符'.因为`int*operator()`看起来像"函数运算符返回指向int的指针"而不是"指针取消引用运算符返回int",所以会有歧义.此外,如果关键字"operator"始终位于第一位,则解析器更容易实现(并且更好地捕获错误). (2认同)

fre*_*low 7

直接来自Bjarne的嘴:

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

这些解释是必要的,因为这种机制是独特的,因此有点疣.给出一个选择,我可能会介绍prefixpostfix关键字,但那时似乎不可行.然而,唯一真正重要的一点是该机制可以工作,并且可以被真正需要它的少数程序员理解和使用.

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