© 2003 Prentice Hall, Inc. All rights reserved. 1 Chapter 8 - Operator Overloading Outline 8.1 Introduction 8.2 Fundamentals of Operator Overloading 8.3 Restrictions on Operator Overloading 8.4 Operator Functions as Class Members vs. as friend Functions 8.5 Overloading Stream-Insertion and Stream-Extraction Operators 8.6 Overloading Unary Operators 8.7 Overloading Binary Operators 8.8 Case Study: Array Class 8.9 Converting between Types 8.10 Case Study: A String Class 8.11 Overloading ++ and -- 8.12 Case Study: A Date Class 8.13 Standard Library Classes string and vector © 2003 Prentice Hall, Inc. All rights reserved. 2 8.1 Introduction •Sử dụng các toán tử với các đối tượng (operator overloading) – đối với một số lớp, sử dụng toán tử trong sáng hơn sử dụng các lời gọi hàm object2 = object1.add(object2); object2 = object2 + object1; – toán tử cảm ngữ cảnh (sensitive to context) Ví dụ • << – chèn vào dòng (Stream insertion), phép dịch trái nhị phân (bitwise left-shift) • + –thực hiện tính cộng cho nhiều kiểu dữ liệu (integers, floats, etc.) © 2003 Prentice Hall, Inc. All rights reserved. 3 8.2 Fundamentals of Operator Overloading •Các kiểu dữ liệu –Có sẵn (Built in) (int, char) hoặc kiểu người dùng (user- defined) –Có thể sử dụng các toán tử có sẵn cho các kiểu dữ liệu người dùng • Không thể tạo toán tử mới • Overloading operators –Tạo một hàm của lớp – Đặt tên hàm là operator tiếp theo là ký hiệu • Operator+ dành cho phép cộng + © 2003 Prentice Hall, Inc. All rights reserved. 4 8.2 Fundamentals of Operator Overloading •Sử dụng toán tử với một đối tượng –Nó phải được overloaded cho lớp đó • ngoại trừ: • phép gán, = – phép gán từng thành viên của đối tượng này cho đối tượng kia (Memberwise assignment between objects) • toán tử địa chỉ, & –trả về địa chỉ của đối tượng •cả hai đều có thể được overloaded • Overloading cho ký hiệu ngắn gọn object2 = object1.add(object2); object2 = object2 + object1; © 2003 Prentice Hall, Inc. All rights reserved. 5 8.3 Restrictions on Operator Overloading • Không thể thay đổi: –Hoạt động của các toán tử đối với các kiểu dữ liệu có sẵn •ví dụ., không thể thay đổi phép cộng số nguyên –Thứ tự ưu tiên của các toán tử – Quan hệ kết hợp - Associativity (left-to-right hoặc right-to- left) –Số lượng toán hạng (operand) • & là toán tử đơn, chỉ dành cho một toán hạng • Không thể tạo các toán tử mới • Các toán tử phải được overloaded một cách tường minh –Overload+ không có nghĩacả += cũng được overload © 2003 Prentice Hall, Inc. All rights reserved. 6 8.3 Restrictions on Operator Overloading Operators that cannot be overloaded . .* :: ?: sizeof Operators that can be overloaded + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[] © 2003 Prentice Hall, Inc. All rights reserved. 7 8.4 Operator Functions As Class Members Vs. As Friend Functions • aa@bb Î aa.operator@(bb) hoặc operator@(aa,bb) • @aa Î aa.operator@( ) hoặc operator@(aa) • aa@ Î aa.operator@(int) hoặc operator@(aa,int) • Operator functions – Member functions •Sử dụng từ khóa this để ngầm lấy tham số – là toán hạng bên trái đối với các toán tử hai ngôi (ví dụ +) – là toán hạng duy nhất đối với các toán tử một ngôi • Toán tử và toán hạng bên trái nhất phải thuộc cùng lớp – Non member functions •Cần tham số cho cả hai toán hạng •Có thể lấy các đối tượng không thuộc lớp của toán tử •Phải là friend để truy nhập các dữ liệu private hoặc protected © 2003 Prentice Hall, Inc. All rights reserved. 8 8.4 Operator Functions As Class Members Vs. As Friend Functions • Các phép toán có tính giao hoán – phép + cần có tính giao hoán •cả “a + b” và “b + a” đều phải chạy được –giả sử ta có hai lớp khác nhau – Overloaded operator chỉ có thể là member function khi lớp của nó ở bên trái • HugeIntClass + long int –trường hợp kia, cần một non-member overload function • long int + HugeIntClass © 2003 Prentice Hall, Inc. All rights reserved. 9 8.5 Overloading Stream-Insertion and Stream-Extraction Operators • << và >> – đã được overloaded để xử lý từng kiểu built-in –cũng có thể overload để xử lý kiểu dữ liệu người dùng • Overloaded << operator – toán tử trái thuộc kiểu ostream & •chẳng hạn đối tượng cout tại cout << classObject –tương tự, overloaded >> cần toán tử trái kiểu istream & –Vậy, cả hai phải là non-member function •Chương trình ví dụ – Class PhoneNumber •Lưu trữ một số điện thoại –In số điện thoại đã được định dạng tự động • (123) 456-7890 © 2003 Prentice Hall, Inc. All rights reserved. Outline 10 fig08_03.cpp (1 of 3) 1 // Fig. 8.3: fig08_03.cpp 2 // Overloading the stream-insertion and 3 // stream-extraction operators. 16 // PhoneNumber class definition 17 class PhoneNumber { 18 friend ostream &operator<<( ostream&, const PhoneNumber & ); 19 friend istream &operator>>( istream&, PhoneNumber & ); 20 21 private: 22 char areaCode[ 4 ]; // 3-digit area code and null 23 char exchange[ 4 ]; // 3-digit exchange and null 24 char line[ 5 ]; // 4-digit line and null 25 26 }; // end class PhoneNumber 28 // overloaded stream-insertion operator; cannot be 29 // a member function if we would like to invoke it with 30 // cout << somePhoneNumber; 31 ostream &operator<<( ostream &output, const PhoneNumber &num ) 32 { 33 output << "(" << num.areaCode << ") " 34 << num.exchange << "-" << num.line; 35 36 return output; // enables cout << a << b << c; 37 38 } // end function operator<< function prototype cho các hàm overload các toán tử >> và << Chúng phải là các non-member friend function, vì đối tượng của lớpPhonenumber xuất hiện bên phải toán tử. cin << object và cout >> object Biểu thức: cout << phone; được hiểu là lời gọi hàm: operator<<(cout,phone); output là một tên khác cho cout. cho phép gọi object thành chuỗi cout << phone1 << phone2; trước hết gọi operator<<(cout, phone1), và trả về cout. tiếp theo, cout << phone2 chạy. [...]... tham số • !s trở thành s .operator! () class String { public: bool operator! () const; }; – nếu là non-member function, cần một tham số • s! trở thành operator! (s) class String { friend bool operator! ( const String & ) } © 2003 Prentice Hall, Inc All rights reserved 14 8.7 Overloading Binary Operators • non-static member function, một tham số class String { public: const String &operator+ =( const String... cout >( cin, phone ) cin >> phone; 65 66 cout... qua một số ký tự input, số lượng được chỉ ra tại tham số (mặc định là 1) 40 41 42 43 44 45 46 47 48 49 50 51 52 fig08_03.cpp (2 of 3) // overloaded stream-extraction operator; cannot be // a member function if we would like to invoke it with // cin >> somePhoneNumber; istream &operator> >( istream &input, PhoneNumber &num ) { input.ignore(); // skip ( input >> setw( 4 ) >> num.areaCode; // input area code... class String { public: const String &operator+ =( const String & ); }; – y += z tương đương với y .operator+ =( z ) • non-member function, hai tham số – tham số phải là đối tượng hoặc tham chiếu đến đối tượng class String { friend const String &operator+ =( String &, const String & ); }; – y += z tương đương với operator+ =( y, z ) © 2003 Prentice Hall, Inc All rights reserved . Chapter 8 - Operator Overloading Outline 8.1 Introduction 8.2 Fundamentals of Operator Overloading 8.3 Restrictions on Operator Overloading 8.4 Operator Functions. friend Functions 8.5 Overloading Stream-Insertion and Stream-Extraction Operators 8.6 Overloading Unary Operators 8.7 Overloading Binary Operators 8.8 Case