1

I would like to leave the two instances unchanged, and return a new one. Currently I am doing it this way:

class myClass {

    public:

        myClass operator +(const myClass &obj) {

            myClass ret = *this;

            // some operation

            return ret;

        }

        // functions...

};

It works, but I am not sure, if it is the correct way


Edit

The operator + is just an example. I'm just curious, how the immutable functions/methods should be written in C++

Iter Ator
  • 8,226
  • 20
  • 73
  • 164
  • Why are you unsure? It does what you want right? – NathanOliver Jan 15 '16 at 15:26
  • I believe there's nothing wrong with what you wrote – Transcendental Jan 15 '16 at 15:28
  • I am unsure, because I'm just a beginner, and I've created this code by myself – Iter Ator Jan 15 '16 at 15:28
  • 1
    @NathanOliver Lot's of things that appear to do what you want might be 1. UB, 2. bad practice, with downsides you haven't thought of yet. However, it does make for a bit of a vague/open-ended question for SO. That said, in this case, I believe this is a reasonable approach. – BoBTFish Jan 15 '16 at 15:28
  • 2
    Looks fine. Personally I'd write a comment for the first line, indicating explicitly that the copy constructor is being invoked. Or, just invoke the appropriate constructor directly. For example, if `myClass` represented an integer, you could either write what you have now: `myClass ret = *this; ret.value += other.value;`, or you could avoid the copy and construct a new one straight away with `myClass ret(this->value + other.value)`. – CompuChip Jan 15 '16 at 15:29
  • 1
    @BoBTFish That is what I was getting at. I was hoping the OP would add a little more to the question. – NathanOliver Jan 15 '16 at 15:30
  • 5
    You're missing one thing: the function should be `const`. `myClass operator +(const myClass &obj) const`. – molbdnilo Jan 15 '16 at 15:40
  • 2
    [This thread](http://stackoverflow.com/questions/4421706/operator-overloading) is an excellent resource. – Carlton Jan 15 '16 at 15:47

1 Answers1

1

If myClass is supposed to be immutable under addition, you probably want to make operator+ a free function rather than a class member. (You might have to make it a friend function.)

myClass operator+(const myClass &lhs, const myClass &rhs) {
  return myClass( /* some operation */ );
}

Note that both operands are taken by const reference, so you know you cannot accidentally change them (maintaining the immutability property). You're returning a new instance of myClass, which is now immutable. You construct and return the result in one step, because, if myClass really is immutable, you might not be able to default construct one and then set its value.

Here's a stupid example:

class myClass {
  public:
    explicit myClass(int x) : m_x(x) {}
    friend myClass operator+(const myClass &lhs, const myClass &rhs);
  private:
    int m_x;
};

myClass operator+(const myClass &lhs, const myClass &rhs) {
  return myClass(lhs.m_x + rhs.m_x);
}

If you really want to implement it as a class method, the method should be marked const to ensure the implementation doesn't accidentally mutate the left-hand instance.

Binary arithmetic operators (like operator+) are often defined in terms of the arithmetic self-assignment operators (like operator+=), which are obviously not immutable. If we add this method to myClass:

myClass &operator+=(const myClass &rhs) {
  m_x += rhs.m_x;
  return *this;
}

Then the common idiom for defining operator+ would be:

myClass operator+(const myClass &lhs, const myClass &rhs) {
  myClass result = lhs;
  result += rhs;
  return result;
}

Now the implementation of operator+ doesn't require any of the private members of the class, so it no longer needs to be declared as a friend function.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175