Here is how to overload "<<" which turns out to be a pointer to an operator rather than an operator.
ostream &operator<<(ostream &os, quat Q){ Q.print(&os); return(os); }
Overloading the "+" operator is similar.
quat operator+(quat Q1, quat Q2){ quat QQ; QQ.add(Q1,Q2)); return(QQ); }
Function overloading is much more straightforward. We might wish to be able to add a real number to a quaternion so we write a new function. First we add it to our class declaration:
class quat { public: void set(float, float, float, float); void print(quat); void add(quat, quat); void add(float, quat); void sub(quat, quat); void mul(quat, quat); void div(quat, quat);private: float r; // real part float i; float j; float k; };
And then the code for the new function:
quat quat::add(quat Q, float F){ quat QQ; QQ.set(Q.r+F,Q.i,Q.j,Q.k)); return(QQ); }
Overloading the "+" operator has one additional wrinkle: we need two overloads.
quat operator+(quat Q1, float Q2){ quat QQ; QQ.add(Q1,Q2)); return(QQ); }
quat operator+(float Q1, quat Q2){ quat QQ; QQ.add(Q2,Q1)); return(QQ); }
After this work, we can just write
Q+1.04
or
9.02 + Q
and get the addition we expect if Q is a valid quaternion variable.
We could have produced a second overloaded "add" function
add(float, quat)
but this seems overkill since in practice the user will never use "add".
Indeed, most experienced C++ programers would have just written
the 2-quat version of add and then for the real versions written
quat operator+(quat Q, float F){ quat QQ; QQ.set(F,0,0,0); QQ.add(QQ,Q)); return(QQ); }
quat operator+(float F, quat Q){ quat QQ; QQ.set(F,0,0,0); QQ.add(QQ,Q); return(QQ); }