Multiplication operator overloaded to represent the cross-product

Operator overloading seems to be one of the most prominent controversies in programming--at least from my end of the food chain.

Every time I learn a new programming/scripting language (which will henceforth be known collectively as "computer languages" just to save me the hassle of differentiating them), I always check to see if it has operator overloading functionality. C++ supports it, as does Python. I use C++ a fair bit for simple applications and for the odd game modification, but Python takes a back seat unless I need something quick-and-dirty that I don't want to take the time to debug. On the other hand, Java and PHP which I both use fairly often, do not support the overloading of operators.

It's probably good to first figure out just what an overloaded operator is: it's a bit of instruction that tells the program or script what to do in the case that one of the basic operators (such as +, *, =) is used in a bit of code.

Let's say, for example, that in C++ we wanted to set up a Vector3D class, which has three values: X, Y, and Z. In some case, we're going to end up wanting to get a cross product of two 3D vectors. For this example, though it may not be considered good practice, we're going to use the * (multiplication) operator to handle our cross product.

class Vector3D {
public:
    float X;
    float Y;
    float Z;

    Vector3D(float x = 0.0f, float y = 0.0f, float z = 0.0f) {
        X = float(x); Y = float(y); Z = float(z);
    };

    Vector3D operator* (Vector3D& With) {
        return Vector3D(
            (this->Y * With.Z) - (this->Z * With.Y),
            (this->Z * With.X) - (this->X * With.Z),
            (this->X * With.Y) - (this->Y * With.X)
        );
    };

    void operator*= (Vector3D& With) {
        Vector3D Result = Vector3D(this->X,this->Y,this->Z) * With;
        this->X = Result.X;
        this->Y = Result.Y;
        this->Z = Result.Z;
    };
};

Now that we've overloaded the operator (and the = operator), we can apply this to a bit of code:

void main() {
    Vector3D A(7,5,2);
    Vector3D B(6,2,1);
    printf("%f %f %f\\n",(A*B).X,(A*B).Y,(A*B).Z);
    A *= B;
    printf("%f %f %f\\n",A.X,A.Y,A.Z);
}

That code produces the following:

Result of Vector3D cross product

Which outputs the correct result.

In this particular case, operator overloading is very handy. A developer may prefer doing A *= B; instead of something weird like A.CrossProductOf(B);. Now keep in mind, this isn't the most useful application of operator overloading--I mean, until you're the lead designer for the CryEngine 3 project, that may not come in all too handy.

A good place to think about a useful application of this might be strings. Though these are not overloaded operators, these functions in Python are quite handy:

x = "A String";
# x[4] == 'r'
# x[4:6] == 'ri'
x += " and another String...";
# x == 'A String and another String...'
x *= 2;
# x == 'A String and another String...A String and another String...'

Now you can actually see how useful this syntax is. wxWidgets, a C++ GUI Framework, supports a lot of these functions and they come in quite useful in practice:

int MyAge = Get_User_Age(); // A dummy function; let's assume this returns 30. wxString& MyName = Get_User_Name(); // Another dummy; returns "Tom" wxString& MyString = wxString("You, "); MyString += MyName + wxString(", are ") + wxString::Format("%d",MyAge) + wxString(" years old.");

Once executing the code above, the string value of MyString would be "You, Tom, are 30 years old." Now, this isn't the best use of the concatenation operator, as the following two examples do the same thing (though the second is a better choice, really):

int MyAge = Get_User_Age();
wxString& MyName = Get_User_Name();
wxString& MyString = wxString("You, ");
MyString.Append(MyName).Append(wxString(", are ")).Append(wxString::Format("%d",MyAge)).Append(wxString(" years old."));

int MyAge = Get_User_Age();
wxString& MyName = Get_User_Name();
wxString& MyString = wxString::Format("You, %s, are %d years old.",MyName,MyAge);

For operator overloading in general, Python is implemented almost the same way, except instead of Vector3D operator* (Vector3D& With) {}, you simply have def __mul__(this, With):, which also has a generic return type. Not a huge difference.

But now we get to the other side of the coin--is operator overloading necessary?

Of course, this is my opinion, but the obvious answer is NO.

Now, don't get me wrong, I love overloading operators quite a bit, and I really wished that PHP allowed for overriding of the [] operator.

But honestly, there's no real need for the operators. As a programmer, I can design an equally effective program with or without them, and often times they can get to be tedious or superfluous; like the < and > operators. What do they do when applied to arrays A and B? Number of values in the array? What about strings? Length of the string? What if you wanted a dot product operator on a matrix? There's no • operator... In these cases and several more, you'd have to make up your own function, look up documentation, or simply guess in a massive bout of trial and error.

Nevertheless, it all boils down to this: In C++, I can make a custom array class and do the following:

MyIntArrayClass *Array = new MyIntArrayClass();
Array->Push(5)->Push(6)[0]; // == 5

But in PHP (or Java or anything similar), I have to suffice with this:

$array = new MyIntArrayClass();
$array->Push(5)->Push(6)->Get(0); // == 5

Aww. Poor me.

Next Post