简体   繁体   English

操作员重载如何工作,为什么在我的情况下不起作用?

[英]How does operator overloading work, and why doesn't it work in my case?

I've been provided a driver function that is supposed to demonstrate the results of operator overloading involving complex numbers. 已为我提供了一个驱动程序函数,该函数应演示包含复杂数字的运算符重载的结果。 After reading up on overloading a while I managed to write the code in a way that it successfully compiles, however somewhere along the way the correct values are not being outputted by the program. 阅读了一段时间的重载后,我设法以成功编译的方式编写了代码,但是在此过程中某个地方程序没有输出正确的值。

From what I understand overloading essentially works like a function. 据我了解,重载本质上就像一个函数。 Objects are passed and the "function" can then do arithmetic/whatever with it and return a new object. 传递对象,然后“函数”可以对其进行算术/任何操作,然后返回一个新对象。 Where I'm slightly lost though, is how overloading knows what values are being passed. 不过,我有点迷失的地方是重载如何知道要传递的值。 For example, in my case I overloaded the "+" and "=" operators in order to add two complex numbers in the form "x = y + z". 例如,在我的情况下,我重载了“ +”和“ =”运算符,以便以“ x = y + z”的形式添加两个复数。 When the compiler comes across the "=" symbol, I'm assuming it simply passes whatever is on both the left and right side and passes those? 当编译器遇到“ =”符号时,我假设它只是通过了左侧和右侧的所有内容并通过了这些内容? Same with "+". 与“ +”相同。 In this case it would be passing "y" since it's the object on the left and "z" because it's the object on the right? 在这种情况下,它将传递“ y”,因为它是左边的对象,传递“ z”,因为它是右边的对象?

Here's my current "complex" class which includes the overloading definitions. 这是我当前的“复杂”类,其中包括重载定义。

class Complex {

private:
double realPart;
double imaginaryPart;

public:
// friends
friend ostream & operator<<(ostream &out, const Complex &c);
friend istream & operator>>(istream &in,  Complex &c);

// constructors
Complex()
{
    realPart = 0;
    imaginaryPart = 0;
}

Complex(double real)
{
    realPart = real;
    imaginaryPart = 0;
}

Complex(double real, double imaginary)
{
    realPart = real;
    imaginaryPart = imaginary;
}
// end of constructors

// + overloading
Complex operator+(Complex const &c)
{
    Complex Add;
    Add.realPart = realPart + c.realPart;
    Add.imaginaryPart = imaginaryPart + c.imaginaryPart;
    return Add;
}

// - overloading
Complex operator-(Complex const &c)
{
    Complex Subtract;
    Subtract.realPart = realPart - c.realPart;
    Subtract.imaginaryPart = imaginaryPart - c.imaginaryPart;
    return Subtract;
}

// * overloading
Complex operator*(Complex const &c)
{
    Complex Multiply;
    Multiply.realPart = (realPart * c.realPart) - (imaginaryPart * c.imaginaryPart);
    Multiply.imaginaryPart = (realPart * c.imaginaryPart) - (imaginaryPart * c.realPart);
    return Multiply;
}

// = overloading
Complex operator=(Complex const &c)
{
    Complex Assignment;
    Assignment.realPart = realPart;
    Assignment.imaginaryPart = imaginaryPart;
    return Assignment;
}

// == overloading
bool operator==(Complex const &c)
{
    Complex Compare;
    if (Compare.realPart == realPart && Compare.imaginaryPart == imaginaryPart)
    {
        return true;
    }
    else
    {
        return false;
    }
}

    // != overloading
bool operator!=(Complex const &c)
{
    Complex NotEqual;
    if (NotEqual.realPart == realPart && NotEqual.imaginaryPart == imaginaryPart)
    {
        return false;
    }
    else
    {
        return true;
    }
}

};

// << overloading
ostream& operator<<(ostream& out, const Complex &c)
{
    out << c.realPart;
    if (c.imaginaryPart >= 0)
    {
        out << " + " << c.imaginaryPart << "i" << endl;
    }
    else
    {
        out << " - " << fabs (c.imaginaryPart) << "i" << endl;
    }

    return out;
}

// >> overloading
istream& operator>>(istream &in, Complex &c)
{
    in >> c.realPart;
    in >> c.imaginaryPart;
    return in;
}

And here's the driver program: 这是驱动程序:

int main()
{
    for (double i = 1; i < 10; ++ i)
    {
        Complex y{i * 2.7, i + 3.2};
        Complex z{i * 6, i + 8.3};

        Complex x;
        Complex k;

        std::cout << "Enter a complex number in the form: (a, b)\n? ";
        std::cin >> k; // demonstrating overloaded >>
        std::cout << "x: " << x << "\ny: " << y << "\nz: " << z << "\nk: " << k << '\n'; // demonstrating overloaded <<

        x = y + z; // demonstrating overloaded + and =
        std::cout << "\nx = y + z:\n" << x << " = " << y << " + " << z << '\n';
        x = y - z; // demonstrating overloaded - and =
        std::cout << "\nx = y - z:\n" << x << " = " << y << " - " << z << '\n';
        x = y * z; // demonstrating overloaded * and =
        std::cout << "\nx = y * z:\n" << x << " = " << y << " * " << z << "\n\n";

        if (x != k)
        { // demonstrating overloaded !=
            std::cout << x << " != " << k << '\n';
        }

        std::cout << '\n';
        x = k;

        if (x == k)
        {
            // demonstrating overloaded ==
            std::cout << x << " == " << k << '\n';
        }

        std::cout << std::endl;
}
}

Upon running, the problem seems to be with the object "x". 运行时,问题似乎出在对象“ x”上。 Entering "5 2" will still output "x: 0 + 0i" This leads me to believe the issue is with either overloading of "=" or the stream operators. 输入“ 5 2”仍将输出“ x:0 + 0i”,这使我相信问题在于“ =”的重载或流运算符。 That said, I can't quite figure out why nothing is happening. 就是说,我不太清楚为什么什么也没发生。

Is there an error in how I've constructed the "=" overloading definition as I think, or is it maybe something bigger I'm missing? 我如何构造“ =”重载定义时出现错误,还是我缺少的东西更大?

Your = is wrong; 您的=错误; it should return *this . 它应该返回*this

Complex& operator=(Complex const &c)
{
  realPart = c.realPart;
  imaginaryPart = c.imaginaryPart;
  return *this;
}

Fix that and most of the rest looks sane. 解决该问题,其余大多数看起来都很理智。

The operator=() is not correct: user Yakk - Adam has already shown you how to fix it. operator=()不正确:用户Yakk - Adam已经向您展示了如何修复它。 To give you insight on why it is wrong and what return *this does; 让您深入了解错误的原因和return *this let's look at your original function: 让我们看看您的原始功能:

 Complex operator=(Complex const &c) { Complex Assignment; Assignment.realPart = realPart; Assignment.imaginaryPart = imaginaryPart; return Assignment; } 

Here your signature takes a const reference to another Complex object this part is correct. 在这里,您的签名采用了const引用,该引用是正确的另一个Complex对象。 Your return type is a Complex object this is in essence wrong because you don't want to return a copy of an object. 您的返回类型是一个Complex对象,这在本质上是错误的,因为您不想返回对象的副本。 The objective here is to perform assignment. 这里的目的是执行分配。 This means you must make changes to the original LHS instance. 这意味着您必须更改原始的LHS实例。

In the expression A = B + C ; 在表达式A = B + C ; A is considered the LHS instance. A被视为LHS实例。 Here you want to assign the expression (B + C) which are both RHS values. 在这里,您要分配均为RHS值的表达式(B + C)

So when Yakk - Adam showed you how to fix this by: 因此,当Yakk - Adam向您展示了如何通过以下方法解决此问题时:

 Complex& operator=(Complex const &c) { realPart = c.realPart; imaginaryPart = c.imaginaryPart; return *this; } 

One of the differences here is that the return type is now a Reference to a specific object instead of a copy to an object. 此处的区别之一是,返回类型现在是对特定对象的Reference ,而不是对对象的副本。

Another difference is that there is no need to create a local temporary copy as you did in your original version: 另一个区别是,无需像原始版本中那样创建本地临时副本:

 Complex Assignment; // this is not needed 

By removing that from operator=() he simply replaced these lines of code: 通过从operator=()删除它,他仅替换了以下代码行:

 // Assignment.realPart = realPart; // To realPart = c.realPart; // Assignment.imaginaryPart = imaginaryPart; // To imaginaryPart = c.imaginaryPart; 

Here you are using the class's members directly and assigning to them the value that belongs to the other or c that is passed to the operator. 在这里,您将直接使用类的成员,并为他们分配属于另一个或传递给运算符c的值。

Then finally to return your LHS instance with the updated value; 然后最后返回具有更新值的LHS实例; this is where you have to return a dereferenced this pointer. 这是您必须返回解引用的this指针的地方。

What does *this mean? *this是什么意思? The this pointer is a special pointer that belongs to all class and struct types. this指针是一种特殊的指针,它属于所有classstruct类型。 For example any time you have class object: 例如,任何时候您拥有类对象:

class Foo {
public:
    int bar { 10 };

    void addFive();
}; 

You can use the this pointer directly in your member functions: 您可以在成员函数中直接使用this指针:

void Foo::addFive() {
    this->bar += 5; // same as below  (this) belongs to this particular instance.
    // bar += 5;        
}

Regarding your operator=() ; 关于您的operator=() ; since you are returning by reference you can not simply just return this . 由于您是通过reference返回的,因此不能简单地return this This will return the this pointer. 这将返回this指针。 We don't want a pointer to the object as we want a reference to the object; 我们不需要指向对象的指针,因为我们想要引用对象。 so we must deference the this pointer by returning *this . 因此我们必须通过返回*this来引用this指针。

I hope this helps clear things up for you. 我希望这可以帮助您解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM