1 EE 355 Unit 12 Operator Overloading Mark Redekopp
2 Download • $ wget http://ee.usc.edu/~redekopp/ee355/code/complex.tar • $ tar xvf complex.tar
3 Function Overloading • What makes up a signature (uniqueness) of a function – name – number and type of arguments • No two functions are allowed to have the same signature; the following 3 functions are unique and allowable… – void f1(int); void f1(double); void f1(List<int>&); • We say that “f1” is overloaded 3 times
4 Operator Overloading class User{ • C/C++ defines operators (+,*,-,==,etc.) that public: User(string n); // Constructor work with basic data types like int, char, string get_name(); private: double, etc. user.h int id_; • string name_; C/C++ has no clue what classes we’ll define }; and what those operators would mean for #include “ user.h ” these yet-to-be-defined classes User::User(string n) { – name_ = n; Class complex { } user.cpp public: string User::get_name(){ double real, imaginary; return name_; }; } – Complex c1,c2,c3; #include<iostream> c3 = c1 + c2; // should add component-wise #include “ user.h ” – Class List { … int main(int argc, char *argv[]) { }; User u1(“Bill”), u2(“Jane”); User_test.cpp // see if same username – List l1,l2; // Option 1: l1 = l1 + l2; // should append l2 items to l1 if(u1 == u2) cout << “Same”; // Option 2: if(u1.get_name() == u2.get_name()) { cout << “Same” << endl; } return 0: }
5 Operator Overloading w/ Global Functions • Can define global functions int main() with name "operator{+- */…}" { int hour = 9; taking two arguments string suffix = "p.m."; – LHS = Left Hand side is 1 st arg string time = hour + suffix; // WON'T COMPILE…doesn't know how to – RTH = Right Hand side is 2 nd arg // add an int and a string return 0; } • When compiler encounters an string operator+(int time, string suf) operator with objects of { stringstream ss; specific types it will look for an ss << time << suf; return ss.str(); "operator" function to match } int main() and call it { int hour = 9; string suffix = "p.m."; string time = hour + suffix; // WILL COMPILE TO: // string time = operator+(hour, suffix); return 0; }
6 Operator Overloading for Classes class Complex • C++ allows users to write { public: Complex(int r, int i); functions that define what an ~Complex(); Complex operator+(const Complex &rhs); operator should do for a class private; – Binary operators: +, -, *, /, ++, -- int real, imag; – Comparison operators: }; ==, !=, <, >, <=, >= Complex Complex::operator+(const Complex &rhs) – Assignment: =, +=, -=, *=, /=, etc. { Complex temp; – I/O stream operators: <<, >> temp.real = real + rhs.real; • temp.imag = imag + rhs.imag; Function name starts with return temp; ‘ operator ’ and then the actual } operator int main() { • Left hand side is the implied object Complex c1(2,3); Complex c2(4,5); for which the member function is Complex c3 = c1 + c2; // Same as c3 = c1.operator+(c2); called cout << c3.real << "," << c3.imag << endl; // can overload '<<' so we can write: • Right hand side is the argument // cout << c3 << endl; return 0; }
7 Operator Overloading class Complex • C++ allows users to write { public: functions that define what an Complex(int r, int i); ~Complex(); operator should do for a class Complex operator+(const Complex &rhs); – Binary operators: +, -, *, /, ++, -- private; – int real, imag; Comparison operators: }; ==, !=, <, >, <=, >= – Complex Complex::operator+(const Complex &rhs) Assignment: =, +=, -=, *=, /=, etc. { – I/O stream operators: <<, >> Complex temp; temp.real = real + rhs.real; • Function name starts with temp.imag = imag + rhs.imag; ‘ operator ’ and then the actual return temp; } operator int main() • { Left hand side is the implied object Complex c1(2,3); for which the member function is Complex c2(4,5); Complex c3 = c1 + c2; called // Same as c3 = c1.operator+(c2); cout << c3.real << “,” << c3.imag << endl; • Right hand side is the argument // can overload ‘<<‘ so we can write: // cout << c3 << endl; return 0; }
8 Binary Operator Overloading • For binary operators, do the operation on a new object's data members and return that object – Don’t want to affect the input operands data members • Normal order of operations and associativity apply (can’t be changed)
9 Binary Operator Overloading • Make a version for each type of RHS you expect class Complex { int main() public: { Complex(int r, int i); Complex c1(2,3), c2(4,5), c3(6,7); ~Complex() Complex operator+(const Complex &rhs); Complex c4 = c1 + c2 + c3; Complex operator+(int real); // (c1 + c2) + c3 // c4 = c1.operator+(c2).operator+(c3) private: // = anonymous-ret-val.operator+(c3) int real, imag; }; Complex Complex::operator+( const Complex &rhs ) c3 = c1 + c2; c3 = c3 + 5; { Complex temp; } temp.real = real + rhs.real; temp.imag = imag + rhs.imag; return temp; } Complex Complex::operator+( int real ) { Complex temp = *this; temp.real += real; return temp; }
10 Relational Operator Overloading • Can overload class Complex { public: ==, !=, <, <=, >, >= Complex(int r, int i); ~Complex(); Complex operator+(const Complex &rhs); • Return bool bool operator==(const Complex &rhs); int real, imag; }; bool Complex::operator==(const Complex &rhs) { return (real == rhs.real && imag == rhs.imag); } int main() { Complex c1(2,3); Complex c2(4,5); // equiv. to c3 = c1.operator==(c2); if(c1 == c2) cout << “C1 & C2 are equal!” << endl; return 0; } Nothing will be displayed
11 Non-Member Functions int main() • What if the user changes the { Complex c1(2,3); order? Complex c2(4,5); Complex c3 = 5 + c1 ; – int on LHS & Complex on RHS // ?? 5.operator+(c1) ?? – No match to a member function // ?? int.operator+(c1) ?? // there is no int class we can b/c to call a member function // change or write the LHS has to be an instance of return 0; that class } • We can define a non- Doesn't work member function (good old Complex operator+(const int& lhs, const Complex &rhs) { regular function) that takes Complex temp; in two parameters (both the temp.real = lhs + rhs.real; temp.imag = rhs.imag; return temp; LHS & RHS) } int main() – May need to declare it as a { friend Complex c1(2,3); Complex c2(4,5); Complex c3 = 5 + c1 ; // Calls operator+(5,c1) return 0; } Still a problem with this code Can operator+(…) access Complex's private data?
12 Friend Functions • A friend function is a class Dummy { public: function that is not a Dummy(int d) { dat = d }; friend int inc_my_data(Dummy &dum); member of the class but private: int dat; has access to the private }; data members of // don’t put Dummy:: in front of inc_my_data(...) int inc_my_data(Dummy &dum) instances of that class { dum.dat++; • Put keyword ‘friend’ in return dum.dat; } function prototype in int main() class definition { Dummy dumb(5); • Don’t add scope to dumb.dat = 8; // WON'T COMPILE int x = inc_my_data(dumb); cout<< x << endl; function definition } 6
13 Non-Member Functions class Complex • Revisiting the previous { public: problem. Complex(int r, int i); ~Complex(); // this is not a member function friend Complex operator+(const int&, const Complex& ); private: int real, imag; }; Complex operator+(const int& lhs, const Complex &rhs) { Complex temp; temp.real = lhs + rhs.real; temp.imag = rhs.imag; return temp; } int main() { Complex c1(2,3); Complex c2(4,5); Complex c3 = 5 + c1 ; // Calls operator+(5,c1) return 0; } Now things work!
14 Why Friend Functions? • Can I do the following? class Complex { public: • error: no match for 'operator<<' in 'std::cout << c1' Complex(int r, int i); • /usr/include/c++/4.4/ostream:108: note: ~Complex(); candidates are: /usr/include/c++/4.4/ostream:165: Complex operator+(const Complex &rhs); note: std::basic_ostream<_CharT, private: _Traits>& std::basic_ostream<_CharT, int real, imag; _Traits>::operator<<( long int ) [with _CharT = char, }; _Traits = std::char_traits<char>] • /usr/include/c++/4.4/ostream:169: note: int main() std::basic_ostream<_CharT, _Traits>& { std::basic_ostream<_CharT, Complex c1(2,3); _Traits>::operator<<( long unsigned int ) [with cout << c1; // equiv. to cout.operator<<(c1); _CharT = char, _Traits = std::char_traits<char>] cout << endl; • /usr/include/c++/4.4/ostream:173: note: return 0; std::basic_ostream<_CharT, _Traits>& } std::basic_ostream<_CharT, _Traits>::operator<<( bool ) [with _CharT = char, _Traits = std::char_traits<char>] • /usr/include/c++/4.4/bits/ostream.tcc:91: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<( short int ) [with _CharT = char, _Traits = std::char_traits<char>]
Recommend
More recommend