对于我构建的类以及它如何通过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;
};
当我使用以下主要代码调用此代码时:
int main(void)
{
complex a(1.,0.);
complex b;
b = a * 2.;
b = 2. * a;
return 0;
}
我得到“main.cpp”中第二行到最后一行的编译器错误:
错误:'2.0e + 0 * a'
中的'operator *'不匹配
但之前没有错误。如果我将违规行中的“2.0”投射到一个复合体上,那么一切都很好。所以我的问题是,编译器如何/为什么知道在第一行中将double转换为复数但是(似乎)想要在第二行使用operator *的双重版本?
如果我可以派出一个类,比如说Real,它可以从double中获得,并添加如下内容:
const complex operator*(const double &other)
然后我认为这会有效,但我知道我不能这样做(内置类型不能用作基类)。
谢谢!
@MikeSeymore有一个很好的解决方案。添加非成员函数。我最终得到的是:
complex operator*(double lhs, complex const &rhs) {
complex result(lhs,0.);
return result*=rhs;
}
并且对世界都很好。谢谢迈克。
BTW:关于非类重载的讨论Operator overloading outside class
答案 0 :(得分:6)
由于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
值:这会抑制移动语义。