Professional C__ - Marc Gregoire [324]
C++ does not allow you to overload operator.* (just as you can’t overload operator.), but you could overload operator->*. However, it is very tricky, and, given that most C++ programmers don’t even know that you can access methods and members through pointers, it’s probably not worth the trouble. The C++11 shared_ptr template in the standard library, for example, does not overload operator->*.
WRITING CONVERSION OPERATORS
Going back to the SpreadsheetCell example, consider these two lines of code:
SpreadsheetCell cell(1.23);
string str = cell; // DOES NOT COMPILE!
A SpreadsheetCell contains a string representation, so it seems logical that you could assign it to a string variable. Well, you can’t. The compiler tells you that it doesn’t know how to convert a SpreadsheetCell to a string. You might be tempted to try forcing the compiler to do what you want like this:
string str = (string)cell; // STILL DOES NOT COMPILE!
First, the preceding code still doesn’t compile because the compiler still doesn’t know how to convert the SpreadsheetCell to a string. It already knew from the first line what you wanted it to do, and it would do it if it could. Second, it’s a bad idea in general to add gratuitous casts to your program. Even if the compiler allowed this cast to compile, it probably wouldn’t do the right thing at run time. For example, it might try to interpret the bits representing your object as a string.
If you want to allow this kind of assignment, you must tell the compiler how to perform it. Specifically, you can write a conversion operator to convert SpreadsheetCells to strings. The prototype looks like this:
class SpreadsheetCell
{
public:
// Omitted for brevity
operator string() const;
// Omitted for brevity
};
Code snippet from Conversions\SpreadsheetCell\SpreadsheetCell.h
The name of the function is operator string. It has no return type because the return type is specified by the name of the operator: string. It is const because it doesn’t change the object on which it is called. The implementation looks as follows:
SpreadsheetCell::operator string() const
{
return mString;
}
Code snippet from Conversions\SpreadsheetCell\SpreadsheetCell.cpp
That’s all you need to do to write a conversion operator from SpreadsheetCell to string. Now the compiler accepts the following lines and does the right thing at run time:
SpreadsheetCell cell(1.23);
string str = cell; // Works as expected
Code snippet from Conversions\SpreadsheetCell\SpreadsheetCellTest.cpp
You can write conversion operators for any type with this same syntax. For example, here is the prototype for a double conversion operator from SpreadsheetCell:
class SpreadsheetCell
{
public:
// Omitted for brevity
operator string() const;
operator double() const;
// Omitted for brevity
};
Code snippet from Conversions\SpreadsheetCell\SpreadsheetCell.h
The implementation looks as follows:
SpreadsheetCell::operator double() const
{
return mValue;
}
Code snippet from Conversions\SpreadsheetCell\SpreadsheetCell.cpp
Now you can write code like the following:
SpreadsheetCell cell(1.23);
double d1 = cell;
Code snippet from Conversions\SpreadsheetCell\SpreadsheetCellTest.cpp
Ambiguity Problems with Conversion Operators
Note that writing the double conversion operator for the SpreadsheetCell object introduces an ambiguity problem. Consider this line:
SpreadsheetCell cell(1.23);
double d2 = cell + 3.3; // DOES NOT COMPILE IF YOU DEFINE operator double()
This line now fails to compile. It worked before you wrote operator double(), so what’s the problem now? The issue is that the compiler doesn’t know if it should convert cell to a double with operator double() and perform double addition, or convert 3.3 to a SpreadsheetCell with the double constructor and perform SpreadsheetCell addition. Before you wrote operator double(), the compiler had only one choice: Convert 3.3 to a SpreadsheetCell with the double constructor and perform SpreadsheetCell addition. However, now the compiler could do either. It doesn