C++自定义Comp类operator*已定义却报匹配错误的解决方法
嘿,我一眼就看到问题出在哪儿了——你的运算符重载参数类型不对,导致临时对象没法被正确绑定。咱们慢慢拆解:
错误根源
看编译报错里的关键提示:
note: Comp Comp::operator*(Comp&)
note: no known conversion for argument 1 from ‘Comp’ to ‘Comp&’
你写的operator*(Comp &z1)用的是非const的左值引用当参数,但在多项式函数里:
y += (poly[i])*( z^(deg-i) );
z^(deg-i)返回的是一个临时的Comp对象(函数返回值都是右值),C++里非const左值引用是不能绑定临时右值的,这就是编译器报错的直接原因。
另外提一句,你的operator^实现逻辑没问题,但循环里的计算可以优化,不过这不是当前编译失败的原因,先解决眼前的问题。
修复步骤
1. 把运算符参数改成const引用
把所有接收Comp类型参数的成员运算符(包括+、*、/以及对应的复合赋值运算符)的参数,从Comp&改成const Comp&。同时,把那些不会修改当前对象的成员函数(比如arg()、mod()、conj())都加上const关键字——这是C++里的常量正确性规范,也能让函数接受const对象。
比如修改乘法运算符:
// 原来的写法 Comp operator*(Comp &z1){ ... } // 修改后 Comp operator*(const Comp &z1) const { Comp z2(this->re*z1.re - this->im*z1.im, this->re*z1.im + this->im*z1.re); return z2; }
同理,把operator+、operator/、operator+=、operator*=、operator/=这些函数的参数都改成const Comp&,常量成员函数加上const:
double arg() const { double theta = atan(abs(im)/abs(re)); if(re <0){ theta = PI - theta; } if(im <0){ theta *= -1; } return theta; } double mod() const { return sqrt( re*re + im*im ); } Comp conj() const { Comp z1(re, im*-1); return z1; }
2. 验证修复效果
改完之后,多项式函数里的(poly[i])*( z^(deg-i) )就能正常编译了——因为临时对象现在可以绑定到const Comp&参数上。
可选优化:改进operator^实现
你的operator^用二项式展开是对的,但用pow函数处理整数次幂有点浪费,而且ncr的调用可以优化。不过这不是必须的,修复完上面的问题代码就能正常运行了。
改完后的关键代码示例
比如complex.h里的运算符部分:
// 加法运算符 Comp operator+(const Comp &z1) const { Comp z2(this->re+z1.re, this->im+z1.im); return z2; } void operator+=(const Comp &z){ this->re +=z.re; this->im +=z.im; } // 乘法运算符 Comp operator*(double scalar) const { Comp z(this->re*scalar, this->im*scalar); return z; } void operator*=(double scalar){ this->re *=scalar; this->im *=scalar; } Comp operator*(const Comp &z1) const { Comp z2(this->re*z1.re - this->im*z1.im, this->re*z1.im + this->im*z1.re); return z2; } void operator*=(const Comp &z1){ Comp z2(this->re*z1.re - this->im*z1.im, this->re*z1.im + this->im*z1.re); *this = z2; }
总结
说白了就是非const左值引用不能接临时对象,改成const Comp&就解决了,顺便把常量成员函数标记为const,代码也更规范。
内容的提问来源于stack exchange,提问作者L.Gallagher

