Unformatted text preview:

Chapter 10: Operator OverloadingChapter 10: Operator Overloading_________________________________________________________________________________________________________Consider the following C++ code snippet: vector<string> myVector(kNumStrings); for(vector<string>::iterator itr = myVector.begin(); itr != myVector.end(); ++itr) *itr += "Now longer!";Here, we create a vector<string> of a certain size, then iterate over it concatenating “Now longer!” to each of the strings. Code like this is ubiquitous in C++, and initially does not appear all that exciting. How -ever, let's take a closer look at how this code is structured. First, let's look at exactly what operations we're performing on the iterator: vector<string> myVector(kNumStrings); for(vector<string>::iterator itr = myVector.begin(); itr != myVector.end(); ++itr) *itr += "Now longer!";In this simple piece of code, we're comparing the iterator against myVector.end() using the != operator, incrementing the iterator with the ++ operator, and dereferencing the iterator with the * operator. At a high level, this doesn't seem all that out of the ordinary, since STL iterators are designed to look like regu-lar pointers and these operators are all well-defined on pointers. But the key thing to notice is that STL iterators aren't pointers, they're objects, and !=, *, and ++ aren't normally defined on objects. We can't write code like ++myVector or *myMap = 137, so why can these operations be applied to vector<string>::iterator?Similarly, notice how we're concatenating the string “Now longer!” onto the end of the string: vector<string> myVector(kNumStrings); for(vector<string>::iterator itr = myVector.begin(); itr != myVector.end(); ++itr) *itr += "Now longer!";Despite the fact that string is an object, somehow C++ “knows” what it means to apply += to strings.All of the above examples are instances of operator overloading, the ability to specify how operators nor-mally applicable to primitive types can interact with custom classes. Operator overloading is ubiquitous in professional C++ code and, used correctly, can make your programs more concise, more readable, and more template-friendly.There are two overarching purposes of operator overloading. First, operator overloading enables your custom classes to act like primitive types. That is, if you have a class like vector that mimics a standard C++ array, you can allow clients to use array notation to access individual elements. Similarly, when designing a class encapsulating a mathematical entity (for example, a complex number), you can let clients apply mathematical operators like +, -, and * to your type as though it were built into the language. Second, operator overloading enables your code to interact correctly with template and library code. For example, you can overload the << operator to make a class compatible with the streams library, or the < operator to interface with STL containers.- 290 - Chapter 10: Operator OverloadingThis chapter discusses general topics in operator overloading, demonstrating how to overload some of the more common operators. It also includes tricks and pitfalls to be aware of when overloading certain oper-ators.A Word of WarningI would be remiss to discuss operator overloading without first prefacing it with a warning: operator over-loading is a double-edged sword. When used correctly, operator overloading can lead to intuitive, tem-plate-friendly code that elegantly performs complex operations behind the scenes. However, incorrectly overloaded operators can lead to incredibly subtle bugs. Seemingly innocuous code along the lines of *myItr = 5 can cause serious problems if implemented incorrectly, and without a solid understanding of how to overload operators you may find yourself in serious trouble.There is a pearl of design wisdom that is particularly applicable to operator overloading:The Principle of Least Astonishment: A function's name should communicate its behavior and should be consistent with other naming conventions and idioms.The principle of least astonishment should be fairly obvious – you should design functions so that clients can understand what those functions do simply by looking at the functions' names; that is, clients of your code should not be “astonished” that a function with one name does something entirely different. For ex-ample, a function named DoSomething violates the principle of least astonishment because it doesn't communicate what it does, and a function called ComputePrimes that reads a grocery list from a file viol-ates the principle because the name of the function is completely different from the operation it performs. However, other violations of the principle of least astonishment are not as blatant. For example, a custom container class whose empty member function erases the contents of the container violates the principle of least astonishment because C++ programmers expect empty to mean “is the container empty?” rather than “empty the container.” Similarly, a class that is bitwise const but not semantically const violates the principle, since programmers assume that objects can't be modified by const member functions.When working with operator overloading, it is crucial to adhere to the principle of least astonishment. C++ lets you redefine almost all of the built-in operators however you choose, meaning that it's possible to create code that does something completely different from what C++ programmers might expect. For ex-ample, suppose that you are working on a group project and that one of your teammates writes a class CustomVector that acts like the STL vector but which performs some additional operations behind the scenes. Your program contains a small bug, so you look over your teammate's code and find the following code at one point: CustomVector one = /* ... */, two = /* ... */; one %= two;What does the line one %= two do? Syntactically, this says “take the remainder when dividing one by two, then store the result back in one.” But this makes no sense – how can you divide one CustomVector by another? You ask your teammate about this, and he informs you that the %= operator means “remove all elements from one that are also in two.” This is an egregious violation of the principle of least astonish-ment. The code neither communicates


View Full Document

Stanford CS 106L - Operator Overloading

Download Operator Overloading
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Operator Overloading and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Operator Overloading 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?