简体   繁体   中英

Overloading operators “=” and “+” do not work when combined in C++

#include <iostream>
using namespace std;
class A
{
public:
    A(int a)
    {
        length = a;
    }
    ~A(){}

    friend A operator +(A& var1, A& var2);
    A& operator=(A &other);

    int length;
};

A operator +(A& var1, A& var2)
{
    return A(var1.length + var2.length);
}

A& A::operator=(A &other)
{
    length = other.length;
    return *this;
}


int main()
{
    A a(1);
    A b(2);
    A c(3);
    c = a;   // work
    c = a + b;  // does not work
    cout << c.length ;
    return 0;
}

In main(), c = a is successfully compiled but "c = a + b" is not. However, in A& A::operator=(A &other), if I change (A &other) into (A other) then it works. Can anyone help me with this case?

The simplest fix is to make your assignment overload take it's parameter by const reference.

Then the temporary returned by a + b can be used with it.

A& A::operator=(A const & other)
{
    length = other.length;
    return *this;
}

You'll probably want to do the same thing with your operator+ so that c = a + a + a; will work as well.

The problem is that operator + returns a temporary object

friend A operator +(A& var1, A& var2);

But a temporary object may not be bound to a non-const reference that is the type of the parameter of the assignment operator.

A& operator=(A &other);

So the compiler issues an error for statement

c = a + b;

You have three possibility.

The first one os to declare the parameter of the copy assignment operator as constant reference

A& operator=(const A &other);

It is the simplest approach.

The second one is to declare a move assignment operator instead of the copy assignment operator. In this case you explicitly need to define also a copy or move constructor. In this case instead of

c = a;

you have to write

c = std::move( a );   // work

For example

#include <iostream>
using namespace std;
class A
{
public:
    A(int a)
    {
        length = a;
    }
    ~A(){}

    friend A operator +(A& var1, A& var2);
    A& operator=(A &&other);
    A( A && ) = default;
    int length;
};

A operator +(A& var1, A& var2)
{
    return A(var1.length + var2.length);
}
A& A::operator=(A &&other)
{
    length = other.length;
    return *this;
}

int main()
{
    A a(1);
    A b(2);
    A c(3);
    c = std::move( a );   // work
    c = a + b;  // does not work
    cout << c.length ;
    return 0;
}

And at last you could have the both operators simultaneously. For example

#include <iostream>
using namespace std;
class A
{
public:
    A(int a)
    {
        length = a;
    }
    ~A(){}

    friend A operator +(A& var1, A& var2);
    A& operator=(const A &other);
    A& operator=(A &&other);
    A( const A & ) = default;
    int length;
};

A operator +(A& var1, A& var2)
{
    return A(var1.length + var2.length);
}

A& A::operator=(const A &other)
{
    length = other.length;
    return *this;
}

A& A::operator=(A &&other)
{
    length = other.length;
    return *this;
}

int main()
{
    A a(1);
    A b(2);
    A c(3);
    c = a;   // work
    c = a + b;  // does not work
    cout << c.length ;
    return 0;
}

In this case in statement

    c = a;   // work

there will be called the copy assignment operator and in statement

    c = a + b;  // does not work

there will be called the move assignment operator.

Of course you also may have the copy constructor and move constructor simultaneously the same way as the copy assignment operator and the move assignment operator. For your class you could all them define as defaulted. For example

#include <iostream>
using namespace std;
class A
{
public:
    A(int a)
    {
        length = a;
    }
    ~A(){}

    friend A operator +(A& var1, A& var2);
    A& operator=(const A &other) = default;
    A& operator=(A &&other) = default;
    A( const A & ) = default;
    A( A && ) = default;
    int length;
};

A operator +(A& var1, A& var2)
{
    return A(var1.length + var2.length);
}


int main()
{
    A a(1);
    A b(2);
    A c(3);
    c = a;   // work
    c = a + b;  // does not work
    cout << c.length ;
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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