- Effective Operator Overloading
- Typecasts and Conversions
- Input and Output
- Efficiency Concerns
- Testing and Debugging
- Documentation
- Summary
Typecasts and Conversions
Flexible data representation goes hand in hand with a flexible interface. We already said that we wanted to allow construction with various data types; the same might be said for operators and methods.
class Dollar { // ... Dollar(Float other) { _amt = floor(other); _cents = floor((other-_amt)*100) } Dollar operator+(Float other) { Dollar x = Dollar(other); return(*this + x); // Call other operator+ } }
What about operations in the other direction; that is, Float + Dollar rather than Dollar + Float? C++ (like most languages) doesn't have open classes, so we can't add a method to a core class; nor is Float a proper class in that sense, anyway. In a case like this, we would overload an operator outside the class definition.
Dollar operator+(Float f, Dollar d) { return(d + f); // Call existing operator+ }
We could do the same for int and any other similar type. Note that once again we have minimized the amount of duplicate code by using an existing operator or method. In addition, we didn't need to access any internals of Dollar and so we preserved encapsulation. This also prevented the need for a friend declaration of the function prototype inside the class.
If we want to interoperate with Float values, as shown above, it makes sense to allow conversion or typecasting between those types.
class Dollar { //... operator Float() { return(_amt + _cents/100.0); } } pie = Dollar(3,14) value = static_cast<Float>(pie); // 3.14
The set of types you want to interoperate with is up to you. In a case like this, the constructors can act as typecasts themselves, so there would be a kind of correspondence between these. For example, we have a constructor that takes a single Float, so it makes sense to provide a typecast back to a Float.
The string type is often an important one because strings are so fundamental in programming. You should strongly consider a way to convert your object to a string and possibly consider a corresponding constructor. After all, if we want to output an object, we have to represent it as a string.