Correct overload Operator
(Overloading Operator The Right Way)
BY DANNY KALEV, C Pro Translation: Zhou Shang Yan Beejoy
In order to obtain a string of linked lists or complete the accumulation or merge of two objects, Operator , such as String, Date, Complex, or File is often overloaded. However, in terms of design, it is correctly overloaded Operator to face many challenges. In the following paragraph, I will introduce the general policy of selecting the correct overload Operator for the user-defined type.
Consider the following expression:
INT x = 4 2;
The built-in operator adds two types of operands and then returns the right value 6 to the X, so we can say that the built-in operator ' ' is binary, symmetrical and is exchangeable. Operator, it returns a value with the same type of operand. This is a rule that should maintain the characteristics of the corresponding internal operating operator when you overload an operator for the user-defined type.
User-Defined Type With Operator is a very ordinary thing. However, since C provides a variety of implementations, it is easy to cause errors when designing, thereby adversely affecting the correctness, performance and compatibility of code written by standard library components.
Analyze and build the characteristics of the operator to remove the corresponding USER-DEFINE operator.
Step 1: Select a member function or a non-member function?
We can use , or == or other binary operators like using the members of the class, for example:
Class string {public: BOOL OPERATOR == (const string & s); // compare * this and s};
However, this implementation is worthy of doubt. In this case, as a copy of the built-in operator, the overloaded operator violates the symmetry of the internal operator, and the types of the two operators are 'const string * const' (implied This parameter) and 'const string &', which will make some STL operations and some containers do not process these objects correctly.
Another way to take over the way is that the overloaded Operator is defined as an external function, the same type of two parameters, as follows:
String Operator (Const String & S1, Const String S2);
In this case, class string wants to define the overload function of the operator as a friend function:
Class string {public: Friend String Operator (Const String & S1, Const String & S2);
Step 2: Return to the value, return two difficulties
As mentioned earlier, the built-in Operator returns the same right value as its operator type. However, running objects in Caller's stack will be inefficient, especially when processing big objects. Can you replace it with a pointer or a passage? Can't do it here. We ask the variable and the type of return value to be the same, and return the pointer to destroy this feature. Worse, this makes us not use multiple consecutive expressions:
String S1, S2, S3; STRING RES; RES = S1 S2 S3; // Returns unlamed String *
Although there is a solution, it is also a different overload function that other Operator , but this solution does not take into account the other case: When the returned pointer points to a dynamically assigned object, if the caller does not clear this return The pointer will cause memory leakage. So it is obvious, returning string * is a bad idea. So can't you return String &? Similarly, the returned reference must be bound to a legitimate String. Next, since the dynamic allocation object is not, then the second time we don't choose to return a reference to local static variables? Yes, static objects can solve the problem of memory leakage. However, this is still unreliable. For example, in a multi-thread program, two threads may call Operator at the same time, which will cause misuse of String objects. In addition, because static objects remain when the last call is called, we must empty this static String object every time you call Operator . This way, we get conclusions, the value in the returning stack is still the safest and simplest solution.
Step 3: Implement
Everything is going on so far. In the previous we use an external friend function and use the BY Value to return value. So now it is time we have to reload the Opertor function. Once again, we face two options:
Select 1: Intrusive ConcateNation Model
In the Intrusive ConcateNation model, the length of the Operator measurement function parameters, replicates the string to a sufficiently large buffer and return the result (for a concise reason, I ignore uncommon situations such as pile overload):
// Option 1: Intrusive ConcateNationString Operator (Const String & S1, Const String S2) {Int Len = S1.Size () S2.Size (); string result; result.buf = new char [g 1]; STRCPY (Result.buf, S1.BUF); strcat (result.buf, s2.buf); // Concatenate Second String Return Result;}
This implementation can work better, but there is a more concise and more flexible reload-based Operator = solution.
Select 2: Use operator =
We use Operator = to avoid the use of the access, memory allocation, and C functions of the Private data.
// Option 2: using operator = String Operator (Const String & S1, Const String S2) {string result = S1; Result = S2; RETURN RESULT;}
This implementation method is relatively easy and does not access the non-public data of the String class. And, we don't even need to declare it as a friend function. Operator = overload is reserved for the reader as an exercise.
As the broadest example of overloading Operator operators, we discuss the focus of the discussion focused on a String class you wrote. Of course, you can apply the methods and strategies I introduced to any user-defined type. The correct overload Operator is based on the following principles:
● Operator symmetry
● The return value is the same as the operator type
● Use by value to return to the way
● Implementation method based on overload = operator (End)