Overloading Operator + the Right Way (cont'd)

Step 1: Choosing Between a Member Function and a non-Member Function
You can implement binary operators such as +, - and == as member functions of their class, for example:

class String
{
public:
 bool operator==(const String & s); // compare *this and s
}; 

This approach is problematic, though. As opposed to its built-in counterpart, the overloaded operator isn't symmetric in this case; it takes two arguments whose types are 'const String * const' (the implicit this argument) and 'const String &'. Consequently, some STL algorithms and containers won't be able to deal with such objects properly.

The alternative approach is to define the overloaded operator + as an extern function that takes two arguments of the same type:


String operator + (const String & s1, const String s2);

In this case, class String has to declare the overloaded operator as friend:

class String
{
public:
 friend String operator+(const String& s1,const String&s2);
};

Step 2: The Return Value Dilemma
As previously noted, the built-in operator + returns an rvalue of the type of its operands. Yet returning an object on the caller's stack might be inefficient, especially when dealing with large objects. Shouldn't we return a pointer or a reference instead? No, we shouldn't. Returning a pointer would break the requirement that the arguments and return value's types should be identical. Worse yet, chaining multiple expressions would be impossible either:


String s1,s2,s3;
String res;
res=s1+s2+s3; // impossible with String* as a return value

Although there is a workaround, namely defining additional overloaded versions of operator +, this solution is undesirable for another reason. The returned pointer must point to a dynamically allocated object. This can cause memory leaks if the caller fails to delete the returned pointer. Clearly, returning a String* is a bad idea.

What about returning String& ? Here again, the reference returned must be bound to a valid String. Having ruled out the use of a dynamically allocated object, our second choice is returning a reference to a local static object. Indeed a static object solves the memory leak problem but it's still dubious. In a multithreaded application, two threads might invoke operator + simultaneously, thereby corrupting the String object. Furthermore, because static objects retain their state from the previous call, it's necessary to clear the static String object on every invocation of operator +. To conclude, returning the result on the stack is still the safest and simplest solution.




Back to the Beginning
 
Next: Step 3: Implementation

Introduction
Choosing Between a Member Function and a Non-Member Function
Implementation

Return to Get Help with Windows C/C++ Page

Return to Main Get Help Page


 






Overloading the + operator for a user-defined type is a common programming task. However, since C++ offers several implementation approaches, it's relatively easy to make design mistakes that have adverse effects on code correctness, performance and compatibility with Standard Library components.



Analyze the characteristics of the built-in operator and try to imitate them in the corresponding overloaded operator.


Find Out More

All DevX 10-Minute Solutions for C/C++

DevX Tip: Guidelines for Overloading the + Operator

DevX Tip: What are Lvalues and Rvalues?

STL Library Programmer's Guide


TALK BACK
Operator overloading was deliberately omitted from Java because its creators considered it a source of "unnecessary complication." However, C# does support operator overloading, just as does C++. What is your stance regarding operator overloading? Is it an indispensable feature or a source of "unnecessary complication," as Java designers claimed?


Sponsored Links