Sử dụng các toán tử với đối tượng
©2003 Prentice Hall, Inc. All rights reserved.1Chapter 8 - Operator OverloadingOutline8.1 Introduction8.2 Fundamentals of Operator Overloading8.3 Restrictions on Operator Overloading8.4 Operator Functions as Class Members vs. as friend Functions8.5 Overloading Stream-Insertion and Stream-Extraction Operators8.6 Overloading Unary Operators8.7 Overloading Binary Operators8.8 Case Study: Array Class8.9 Converting between Types8.10 Case Study: A String Class8.11 Overloading ++ and --8.12 Case Study: A Date Class8.13 Standard Library Classes string and vector ©2003 Prentice Hall, Inc. All rights reserved.28.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àmobject2 = 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 (bitwiseleft-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.38.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.48.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.58.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.68.3 Restrictions on Operator OverloadingOperators that cannot be overloaded . .* :: ?: sizeof Operators that can be overloaded + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[] ©2003 Prentice Hall, Inc. All rights reserved.78.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ặcprotected ©2003 Prentice Hall, Inc. All rights reserved.88.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.98.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.Outline10fig08_03.cpp(1 of 3)1 // Fig. 8.3: fig08_03.cpp2 // Overloading the stream-insertion and 3 // stream-extraction operators .16 // PhoneNumber class definition17 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 null23 char exchange[ 4 ]; // 3-digit exchange and null24 char line[ 5 ]; // 4-digit line and null25 26 }; // end class PhoneNumber28 // 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 >> objectBiể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ỗicout << phone1 << phone2;trước hết gọioperator<<(cout, phone1), và trả về cout. tiếp theo, cout << phone2 chạy. [...]... Hall, Inc. All rights reserved. 4 8.2 Fundamentals of Operator Overloading Sử dụng tố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) • tố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... được dùng mỗi khi cần sao chép đối tượng •truyền bằng trị (trả về giá trị hoặc tham số) •khởi tạo một đối tượng bằng một bản sao của một đối tượng khác – Array newArray( oldArray ); – newArray là bản sao của oldArray – Prototype • Array( const Array & ); • Phải lấy tham biến –nếu không, tham số được truyền bằng giá trị – trình biên dịch sẽ cố tạo một bản sao bằng cách gọi copy constructor… –lặp... "\n\n"; 65 © 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 tốn tử có sẵn cho các kiểu dữ liệu người dùng • Khơng thể tạo tố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... &operator[]( int ) const; 39 40 private: 41 int size; // array size 42 int *ptr; // pointer to first element of array 43 44 }; // end class Array 45 46 #endif Toán tử != chỉ cần trả về đảo của toán tử == . Vậy, chỉ cần định nghĩa toán tử= = © 2003 Prentice Hall, Inc. All rights reserved. Outline 44 string1.cpp (8 of 8) 179 180 // overloaded output operator 181 ostream &operator<<( ostream... char *sPtr; // pointer to start of string 65 66 void setString( const char * ); // utility function 67 68 }; // end class String 69 70 #endif Overload toán tử gọi hàm () để trả về một xâu con. Toán tử này có thể có số tốn hạng tùy ý. Hai toán tử chỉ số được overloaded, dành cho const và non-const object. © 2003 Prentice Hall, Inc. All rights reserved. Outline 24 array1.cpp (6 of 7) 115 // overloaded... khoảng – No range checking – Không thể so sánh == một cách có nghĩa – Khơng có phép gán mảng (tên mảng là const pointer) – khơng thể nhập/in cả mảng một lúc •mỗi lần một phần tử •Ví dụ: Cài đặt một lớp Array với – Range checking – Array assignment –mảng biết kích thước của mình – Output/input toàn bộ mảng bằng << và >> –So sánh mảng với == và != © 2003 Prentice Hall, Inc. All rights reserved. 16 8.8... getSize() const; // return size 20 21 // assignment operator 22 const Array &operator=( const Array & ); 23 24 // equality operator 25 bool operator==( const Array & ) const; 26 Hầu hết các toán tử được overloaded bằng member function (trừ << và >> phải dùng non-member function). Prototype for copy constructor. © 2003 Prentice Hall, Inc. All rights reserved. Outline 21 array1.cpp... return 0; 85 86 } // end main © 2003 Prentice Hall, Inc. All rights reserved. 8 8.4 Operator Functions As Class Members Vs. As Friend Functions • Các phép tốn có tính giao hốn – phép + cần có tính giao hố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, . reserved.28.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àmobject2. 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