#include #include using namespace std; //-------------------------------------------------------------------- // A class whose only purpose is to let us experiment with operator // and conversion overloading. //-------------------------------------------------------------------- class MyClass { public: // This constructor allows C++ to perform implicit conversions of integers to // MyClass objects. MyClass(int i) { cout << "MyClass(" << i << ")" << endl; _val = i; } // This constructor allows implicit conversion from a string to MyClass. // This is a very artificial idea; for the most part, there is no sensible conversion. MyClass(const char * s) { cout << "MyClass(" << s << ")" << endl; auto it = _string_map.find(s); if ( it != _string_map.end() ) _val = it->second; else _val = 0; } // This addition operator requires a MyClass object on the left-hand-side (lhs) // and another on the right hand side (rhs). C++ will do an implicit conversion // of an int to a MyClass for the rhs argument, though, because of the // constructor we provided, and similarly for a string. // The argument must be 'const' is required for these implicit conversions to take // place. MyClass operator+(const MyClass &other) const { cout << "MyClass(" << _val << ") + MyClass(" << other._val << ")" << endl; return MyClass(_val + other._val); } // We can't use a class method a non-MyClass is on the lhs, // so we use a regular old method. But, we want that method to have // access to the private state of the MyClass object. Thus, 'friend'. // Example use: 4 + myClassObj friend MyClass operator+(int lhs, const MyClass& rhs); // Example use: cout << ... << myClassObj << ... friend ostream& operator<<(ostream& os, const MyClass& t); // You can overload conversion operators in C++. Usually you // do this to enable implicit conversions between primitive types and objects // of your class. In this not-too-unusual case, simply enabling an implicit // conversion to int causes an ambiguity: when confronted with cout << myClassObj, // the compiler doens't know whether to use the overloaded << operator // above, or to implicitly convert myClassObj to an int and then apply // the << operator. To fix that, we modify this method with the 'explicit' // keyword, disabling implicit conversion using it, but still allowing // explicit conversion. explicit operator int() const { return _val; } private: int _val; static const map _string_map; }; // definition / initialization of class static variable const map MyClass::_string_map = {{"one", 1}, {"two", 2}, {"three", 3}}; //-------------------------------------------------------------------------------------- // Here's the regular old method defining the operation with signature int + myClassObj. //-------------------------------------------------------------------------------------- MyClass operator+(int lhs, const MyClass& rhs) { cout << "int(" << lhs << ") + MyClass(" << rhs._val << ")" << endl; return MyClass(lhs + rhs._val); } //-------------------------------------------------------------------------------------- // The regular old method for ostream output //-------------------------------------------------------------------------------------- ostream& operator<<(ostream& os, const MyClass& t) { os << "(operator <<) " << t._val; return os; } //---------------------------------- // Main line starts here //---------------------------------- int main() { cout << "----- 1 ------------------------------------" << endl; MyClass a(0); cout << "----- 2 ------------------------------------" << endl; MyClass b(1); cout << "----- 3 ------------------------------------" << endl; a = a + 1; cout << "----- 4 ------------------------------------" << endl; b = b + "one"; cout << "----- 5 ------------------------------------" << endl; // This version will invoke our << operator cout << "1 + a + b + 4 = " << (1 + a + b + 4) << endl; cout << "----- 6 ------------------------------------" << endl; // This version explicitly converts the result to an int, which is then output cout << "1 + a + b + 4 = " << (int)(1 + a + b + 4) << endl; cout << "----- 7 ------------------------------------" << endl; // Here we do integer addition, then construct a MyClass object, // then move assign it to b. b = 20 + int(a); cout << "b = 20 + int(a) ==> b = " << int(b) << endl; // Will this compile? run? // cout << "----- 8 ------------------------------------" << endl; // a = 2 * (a + b); // cout << "a = 2 * (a + b) ==> a = " << int(a) << endl; }