Question

I know that it's a good idea to make as much of the interface of a class non-member non-friend as possible, and I've just realised that for my 3D vector class, 'Vector3', I can move the +=, -= and so on operators out of the class, leaving just constructors and the copy assignment operator.

The question is: what should this operator look like? I've seen canonical forms of plenty of other operators and have followed their advice, but I haven't seen canonical forms of these operators. I've given what I think it should be below.

The secondary question is: what are these operators even called? Arithmetic assignment operators?

The (relevant) code before:

class Vector3 {
public:
    Vector3& operator+=(const Vector3& rhs);
    float x, y, z;
};

Vector3& Vector3::operator+=(const Vector3 &rhs) {
    x += rhs.x;
    y += rhs.y;
    z += rhs.z;

    return *this;
}

What I've changed it to so far:

class Vector3 {
public:
    float x, y, z;
};

Vector3& operator+=(Vector3& lhs, const Vector3& rhs) {
    lhs.x += rhs.x;
    lhs.y += rhs.y;
    lhs.z += rhs.z;

    return lhs;
}
Was it helpful?

Solution

What you have looks good to me.

By the way, when you come to the operator+, it is common to implement that in terms of +=. (create a copy of lhs, and then call lhs += rhs and return the result)

Don't know if you're already aware of this trick, but since you're concerned about canonical ways to implement these operators, it can't hurt to mention it. :)

OTHER TIPS

What you have looks good.

The basic way to think about this, intuitively, is to think about what you'd like code to look like when you write it. If, in this case, you can write

Vector v, w;

v += w;
w += v;

and so on, you're on the right track.

There are a lot of good rules of thumb to help; see this entry in the C++ FAQ for lots on it.

I wouldn't say "as much of the interface as possible". There isn't much to be gained by making operator+=, operator-= etc. a not-friend not-member.

Some people prefer to make every function possible a non-member non-friend function to resist the temptation of using private member variables. But you are an adult: you can write the function as a public member, and not use the private member variables. I prefer to know that the function is tied to the class, and making it a public member makes it explicit.

Aside note:
Personally, I find that it's often OK to use the private members instead of public accessors (I know -- I'll burn in hell). Not always! -- but often.
In fact, there are few cases where you couldn't make the switch to public accessors in a manner of minutes if you decide you need it. But I recognize it's not a popular view and I don't ask people to follow that philosophy.

There are concrete reasons to make certaint functions and operators "non-friend, non-member". For example, operator<<() when used as the "stream-insertion operator" cannot be made a member because you would have to change the lhs class (the stream).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top