带有多个参数的隐式转换,以及运算符重载

时间:2015-05-12 04:56:48

标签: c++ c++11 implicit-conversion

我目前正在阅读“The C ++ Programming Language”一书。以下是相关代码

class complex {
public:
  complex(double r, double i): re{r}, im{i} {}
  complex(double r): complex{r,0} {}
  complex(): complex{0,0} {}

  complex& operator-=(complex z) {
    this->re -= z.re;
    this->im -= z.im;
    return *this;
  } 
private:
  double re,im;
};

inline complex operator-(complex a, complex b) {
  return a -= b;
}

inline complex operator-(complex z) {
  return{ 0, 0 } - z;
}

一元operator-给出错误 -

  

语法错误:缺少';'在' - '之前

但是,编译器认为以下两种变体都是正确的

inline complex operator-(complex z) {
  return 0 - z;
}

inline complex operator-(complex z) {
  return {-z.real(), -z.imag()};
}

我认为在这两种情况下都会发生隐式转换。 那为什么

inline complex operator-(complex z) {
  return {0,0} - z;
}

标记为错误?

编辑 - 修复operator- =函数调用的返回类型,并添加operator-(),因为它与问题相关。

1 个答案:

答案 0 :(得分:5)

我假设教科书中的示例还提供了二进制文件operator-,因为如果没有这个,即使{0, 0}被隐含地转换为complex,代码也无法编译线。

return{ 0, 0 } - z;

此行无法编译的原因是因为 braced-init-list {0, 0})不是表达式,因此没有类型。因此它不能用作二进制operator-的操作数之一。

return {-z.real(), -z.imag()};起作用的原因是因为标准明确允许它。

§6.6.3/ 2 [stmt.return]

  

return语句的表达式 braced-init-list 称为其操作数。 ...具有任何其他操作数的return语句只能用于返回类型不是 cv void的函数中; return语句初始化通过复制初始化(8.5)从操作数返回的对象或引用。

copy-initialization 在这种情况下是 copy-list-initialization §8.5.4[dcl.init.list] )它会考虑complex(double r, double i)构造函数,因为它不是explicit

operator-=的返回类型也很奇怪,它会修改complex实例,但随后会返回一个副本。典型的实现是

complex& operator-=(complex const& z) {
...
}