C++ 类、隐式转换和运算符重载

标签 c++

关于我构建的类以及它如何通过 C++ 中的运算符重载与内置类型交互,我遇到了一些我不理解的事情。作为我的问题的一个例子,下面是一个(不完整的)复数类:

class complex {
public:
  complex(double real=0., double imag=0.) : _real(real), _imag(imag) {;}
  ~complex() {;}
  complex& operator=(const complex &rhs) {
    if(this!=&rhs) {
      this->_real = rhs._real;
      this->_imag = rhs._imag;
    }
    return *this; 
  }
  complex& operator*=(const complex &rhs) {
    this->_real = this->_real * rhs._real + this->_imag * rhs._imag;
    this->_imag = this->_real * rhs._imag + this->_imag * rhs._real;
    return *this;
  }
  const complex operator*(const complex &other) const {
    complex result = *this;
    result *= other;
    return result;
  }
protected:
  double _real;
  double _imag;
};

当我用下面的 main 调用这段代码时:

int main(void)
{
  complex a(1.,0.);
  complex b;
  b = a * 2.;
  b = 2. * a;
  return 0;
}

我得到“main.cpp”中倒数第二行的编译器错误:

error: no match for ‘operator*’ in ‘2.0e+0 * a’

但之前的行没有错误。如果我将违规行中的“2.0”转换为复合体,那么一切都很好。所以我的问题是,编译器如何/为什么知道在第一行将 double 转换为复数,但(似乎)想在第二行使用 operator* 的 double 版本?

如果我可以派生一个类,比如 Real,它派生自 double 并添加如下内容:

const complex operator*(const double &other)

然后我认为这可行,但我知道我不能这样做(内置类型不能用作基类)。

谢谢!


@MikeSeymore 有一个很好的修复。添加一个非成员函数。我最终得到的是:

complex operator*(double lhs, complex const &rhs) {
  complex result(lhs,0.);
  return result*=rhs;
}

世界上一切都很好。谢谢迈克。

顺便说一句:关于非类重载的讨论 Operator overloading outside class

最佳答案

因为 operator* 是一个成员函数,转换只能应用于它的右侧操作数。左边的操作数必须是 complex 类型。

最简单的解决方法是使其成为非成员:

complex operator*(complex lhs, complex const & rhs) {return lhs *= rhs;}

如果性能很重要,那么您可能希望为 double 提供特化,而不是依赖隐式转换,以避免不必要的零乘法:

// This one can be a member or a friend, according to taste
complex operator*(double rhs) const {return complex(_real * rhs, _imag * rhs);}

// This one can't be a member
complex operator*(double lhs, complex const & rhs) {return rhs * lhs;}

通常,您不应返回 const 值:这会抑制移动语义。

关于C++ 类、隐式转换和运算符重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24454105/

相关文章:

调用 delete[] 后仍可访问 C++ 指针数组

c++ - 为特定操作系统编写代码时,标准库调用与所有操作系统 API 调用之间的权衡是什么?

c++ - 任何函数都可以是删除函数吗?

c++ - 1 智能感知 : no suitable constructor exists to convert from "bool" to "std::basic_string<char, std::char_traits<char>, std::allocator<char>>"

c++ - 将 8/17/2003 转换为 boost::gregorian::date

c++ - GNU LD 符号版本控制和 C++ 二进制向后兼容性

c++ - 有没有办法将这个 "for i"c++ 预处理器宏转换为现代 C++ (11+)?

c++ - 结构的大小和对齐方式

c++ - 如何在错误情况与非错误情况下处理对象破坏

c++ - WINAPI C++ VS 2008 与 VS 2010