c++中的操作符重载

Operator Overloading in C++

本文关键字:重载 操作符 c++      更新时间:2023-10-16

我需要重载c++中的*操作符。因此,我创建了一个名为Element的类,它必须重载此操作符才能处理存储在其中的双精度值。这是我在实现文件中所做的:

#include "Element.h"
#include <iostream>
using namespace std;
// Other code that is not relevant
Element Element::operator * ( const Element &obj)
{
    d *= obj.d;
    return *this;
}

这行不通。它抛出一个错误:"没有匹配'8 * c'中的'operator*'

在主文件中我有:

d = a = 8 * c - 4 + b;

其中d、a、c和b都是Element

类的对象

你必须明白你在这里做什么,你重载了Element类的'*'操作符,但是你这样做的同时期望另一个元素有一个'参数'。

你写的代码实际上是期望这种代码

Element v, w, a;
a = v * w;
如前所述,您可能想看一下:http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/

这是因为您仅为Element * Element重载了操作符*,而对于c * 8,您必须实现Element Element::operator * ( const int i)

可以用非成员重载(如

)匹配8 * c表达式(int, Element)
Element operator* (const Element& leftHandSide, const Element& rightHandSide){
   return Element( leftHandSide.d * rightHandSide.d);
}

通过使用const Element&,您可以使用具有Element::Element(int )等签名的构造函数进行类型转换。

您现有的操作符实现允许您将两个Element对象相乘。但是,根据"主文件"中的客户端代码,您需要能够将Element对象乘以标量值;

所以你需要的是一个额外的操作符,它接受double作为形参:如下所示:
Element Element::operator * ( const double scalar ) const
{
    const Element e( d * scalar );
    return e;
}

这里我假设你的Element类有一个构造函数,它接受一个标量参数,并把它赋值给d。

还要注意,你现有的操作符*的实现在语义上是奇怪的,因为它改变了d的内部状态(带*=)。这肯定不是你想要的……

我有一个解决方案,并警告您的操作符过载。

解决方案:

#include <iostream>
using namespace std;
struct Element {
    double d;
    Element(double d) {this->d = d;}
    Element operator*(const Element &obj) {
        d *= obj.d;
        return *this;
    }
};
Element operator*(const int i, const Element& e) {
    return Element(static_cast<double>(i) * e.d);
}
ostream& operator<<(ostream& os, const Element& e) {
    os << e.d;
    return os;
}
int main() {
        Element e(2);
        cout << "Product of 8 and e: " << 8*e << 'n';
        // This shows why your overload is a bad idea:
        Element a(3);
        cout << "a is " << a << 'n'; // prints 3
        cout << "Now its product with e is: " << a*e << 'n'; // prints 6
        cout << "Surprise: a is now " << a << 'n'; // prints 6
}

你原来的重载没有工作,因为它甚至没有被调用。您的表达式类似于

a = 8*c

,其中8是int类型,当c++从左到右解析这个表达式时,它看到8是int类型,并试图在int类型中搜索操作符*(const Element&)的重载,但它找不到它,因为它不知道也不应该知道任何关于您自己的用户定义类型的信息。因此,如果您希望自己的类与其他类型交互,则需要将operator*的重载作为成员函数嵌入到其他类型中,或者像我在解决方案中所做的那样将其声明为外部函数。

现在是警告。您的原始操作符重载定义不清,因为它修改了原始对象,这被认为是一种意外行为。我在上面的代码中展示了这一点。就像8乘以2会得到16,但同时8除以16。真正需要做的是在乘法运算符中创建一个新元素并返回它:

struct Element {
    double d;
    Element(double d) {this->d = d;}
    Element operator*( const Element &obj) {
        return Element(this->d * obj.d);
    }
};

该死的这些答案花了很多时间…