Ngôn ngữ lập trình - Bài 5: Nạp chồng toán tử

pdf 37 trang vanle 4420
Bạn đang xem 20 trang mẫu của tài liệu "Ngôn ngữ lập trình - Bài 5: Nạp chồng toán tử", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfngon_ngu_lap_trinh_bai_5_nap_chong_toan_tu.pdf

Nội dung text: Ngôn ngữ lập trình - Bài 5: Nạp chồng toán tử

  1. NGÔN NGỮ LẬP TRÌNH Bài 5: Nạp chồng toán tử Giảng viên: Lý Anh Tu ấn Email: tuanla@tlu.edu.vn
  2. Nội dung 1. Nạp chồng toán tử cơ sở ◦ Các toán tử một ngôi ◦ Là hàm thành viên 2. Kiểu đối tượng trả về 3. Hàm bạn, lớp bạn 4. Tham chiếu và nạp chồng ◦ > ◦ Các toán tử: =, [ ], ++, 2
  3. Giới thiệu nạp chồng toán tử  Các toán tử +, -, %, ==, thực ra là các hàm  Chỉ đơn giản được gọi với cú pháp khác: x + 7 ◦ “+” là toán tử hai ngôi ◦ x & 7 là các toán hạng  Hãy tưởng tượng nó là: +(x, 7) ◦ “+” là tên hàm ◦ x, 7 là các đối số ◦ Hàm “+” trả về tổng của các đối số 3
  4. Viễn cảnh nạp chồng toán tử  Các toán tử dựng sẵn ◦ Vd: +, -, =, %, ==, /, * ◦ Đã làm việc với các kiểu C++ dựng sẵn ◦ Ở dạng hai ngôi chuẩn  Chúng ta có thể nạp chồng chúng ◦ Để làm việc với các kiểu của chúng ta ◦ Để cộng các kiểu theo nhu cầu ở dạng ký hiệu mà chúng ta quen thuộc  Luôn luôn nạp chồng cho các thao tác tương đồng 4
  5. Nạp chồng cơ sở  Nạp chồng toán tử ◦ Rất giống nạp chồng hàm ◦ Bản thân toán tử là tên của hàm  Ví dụ khai báo: const Money operator +( const Money& amount1, const Money& amount2); ◦ Nạp chồng + cho các toán hạng kiểu Money ◦ Để hiệu quả cần sử dụng các tham chiếu hằng ◦ Trả về giá trị kiểu Money: cho phép cộng các đối tượng “Money” 5
  6. Nạp chồng “+”  Xét ví dụ trước: ◦ Lưu ý: “+” được nạp chồng không phải hàm thành viên ◦ Định nghĩa bao gồm nhiều thứ hơn là phép cộng đơn giản  Đòi hỏi phát biểu phép cộng kiểu Money  Phải điều khiển các giá trị âm/dương  Các định nghĩa nạp chồng toán tử thường rất đơn giản ◦ Chỉ thực hiện “phép cộng” đặc thù cho kiểu của bạn 6
  7. Định nghĩa “+” Money  Định nghĩa phép “+” cho lớp Money 7
  8. Nạp chồng “==“  Toán tử đẳng thức, == ◦ Cho phép so sánh các đối tượng Money ◦ Khai báo: bool operator ==(const Money& amount1, const Money& amount2);  Trả về kiểu bool với đẳng thức đúng/sai  Cũng không phải hàm thành viên 8
  9. Nạp chồng “==“ cho Money  Định nghĩa toán tử “==“ cho lớp Money: 9
  10. Kiểu đối tượng trả về  Trả về đối tượng hằng ◦ Việc nạp chồng toán tử “+” const Money operator +(const Money& amount1, const Money& amount2); ◦ Trả về một đối tượng hằng  Trả về đối tượng không hằng ◦ Khi không có const trong khai báo: Money operator +( const Money& amount1, const Money& amount2); ◦ Xét biểu thức được gọi: m1 + m2  Trả về đối tượng Money có thể sửa đổi  Nên định nghĩa đối tượng trả về là hằng 10
  11. Nạp chồng toán tử một ngôi  C++ có các toán tử một ngôi ◦ Được định nghĩa cho một toán hạng ◦ Ví dụ, - (phủ định)  x = -y // Gán x bằng phủ định của y ◦ Các toán tử một ngôi khác:  ++,  Các toán tử một ngôi cũng có thể được nạp chồng 11
  12. Nạp chồng “-” cho Money  Khai báo hàm nạp chồng “-” ◦ Đặt bên ngoài định nghĩa lớp: const Money operator –(const Money& amount); ◦ Lưu ý: chỉ một đối số (vì chỉ có một toán hạng)  Toán tử “-” được nạp chồng hai lần ◦ Với hai toán hạng/đối số (hai ngôi) ◦ Với một toán hạng/đối số (một ngôi) ◦ Cần có định nghĩa cho cả hai 12
  13. Định nghĩa “-” nạp chồng  Định nghĩa nạp chồng hàm “-”: const Money operator –(const Money& amount) { return Money(-amount.getDollars(), -amount.getCents()); }  Áp dụng toán tử một ngôi “-” cho kiểu dựng sẵn ◦ Là thao tác đã biết đối với các kiểu dựng sẵn 13
  14. Sử dụng “-” nạp chồng  Xét: Money amount1(10), amount2(6), amount3; amount3 = amount1 – amount2; ◦ Gọi nạp chồng “-” hai ngôi amount3.output(); //Displays $4.00 amount3 = -amount1; ◦ Gọi nạp chồng “-” một ngôi amount3.output(); //Displays -$10.00 14
  15. Nạp chồng như hàm thành viên  Trong các ví dụ trước: các hàm là độc lập ◦ Được định nghĩa bên ngoài lớp  Có thể nạp chồng như là “toán tử thành viên” ◦ Giống như các hàm thành viên khác  Khi toán tử là hàm thành viên ◦ Chỉ có duy nhất một tham số ◦ Đối tượng gọi phục vụ như là tham số thứ nhất 15
  16. Ví dụ toán tử thành viên  Money cost(1, 50), tax(0, 15), total; total = cost + tax; ◦ Nếu “+” được nạp chồng như là toán tử thành viên:  cost là đối tượng gọi  tax là đối số duy nhất ◦ Hãy hình dung là: total = cost.+(tax);  Khai báo “+” trong định nghĩa lớp: ◦ const Money operator +(const Money& amount); ◦ Lưu ý chỉ có một đối số 16
  17. Nạp chồng áp dụng hàm ()  Toán tử gọi hàm, ( ) ◦ Phải được nạp chồng như hàm thành viên ◦ Cho phép sử dụng đối tượng lớp giống như một hàm ◦ Có thể nạp chồng với số lượng đối số bất kỳ  Ví dụ: Aclass anObject; anObject(42); ◦ Nếu ( ) được nạp chồng nạp chồng lời gọi 17
  18. Các nạp chồng khác  &&, ||, và toán tử dấu phẩy ◦ Phiên bản định nghĩa trước làm việc với kiểu bool ◦ Sử dụng đánh giá tắt ◦ Khi nạp chồng không sử dụng đánh giá tắt nữa  Nói chung không nên nạp chồng những toán tử này 18
  19. Hàm bạn  Hàm không phải hàm thành viên ◦ Nhắc lại: toán tử nạp chồng là hàm không phải hàm thành viên  Chúng truy cập dữ liệu thông qua hàm truy cập và hàm biến đổi  Rất kém hiệu quả (phụ phí lời gọi)  Hàm bạn có thể truy cập trực tiếp dữ liệu lớp private ◦ Không phụ phí, hiệu quả hơn  Do vậy: Tốt nhất là nạp chồng như hàm bạn cho toán tử không phải hàm thành viên 19
  20. Hàm bạn  Hàm bạn của một lớp ◦ Không phải hàm thành viên ◦ Truy cập trực tiếp tới các thành viên private  Giống như cách hàm thành viên làm  Sử dụng từ khóa friend trước khai báo hàm ◦ Được đặc tả trong định nghĩa lớp ◦ Nhưng không phải là hàm thành viên  Sử dụng hàm bạn để nạp chồng toán tử ◦ Cải thiện hiệu quả thực hiện ◦ Tránh gọi hàm thành viên truy cập/biến đổi 20
  21. Lớp bạn  Toàn bộ lớp có thể là bạn ◦ Tương tự như hàm là bạn của lớp ◦ Ví dụ lớp F là bạn của lớp C  Tất cả hàm thành viên lớp F là bạn của C  Chiều ngược lại không đúng  Cú pháp: friend class F ◦ Nằm bên trong định nghĩa của lớp cho phép 21
  22. Tham chiếu  Tham chiếu định nghĩa: ◦ Tên của một vị trí lưu trữ ◦ Tương tự như “con trỏ”  Ví dụ về tham chiếu đứng độc lập ◦ int robert; int& bob = robert;  bob là tham chiếu tới vị trí lưu trữ của robert  Những thay đổi với bob sẽ ảnh hưởng tới robert 22
  23. Sử dụng tham chiếu  Dường như nguy hiểm  Hữu ích trong một số trường hợp:  Truyền tham chiếu ◦ Thường được sử dụng để thi hành kỹ thuật này  Trả về một tham chiếu ◦ Cho phép các thi hành nạp chồng toán tử được viết tự nhiên hơn ◦ Tưởng tượng như là trả về một bí danh cho biến 23
  24. Trả về tham chiếu  Cú pháp: double& sampleFunction(double& variable); ◦ double& và double là khác nhau ◦ Phải giống nhau trong khai báo hàm và đầu đề  Mục trả về phải có một tham chiếu ◦ Chẳng hạn như một biến kiểu đó ◦ Không thể là biểu thức chẳng hạn như “x+5”  Không có vị trí bộ nhớ để trỏ đến  Ví dụ định nghĩa hàm double& sampleFunction(double& variable) { return variable; } 24
  25. Nạp chồng >  Cho phép nhập và xuất các đối tượng ◦ Tương tự như nạp chồng các toán tử khác  Cải thiện tính khả đọc ◦ Giống như tất cả các nạp chồng toán tử ◦ Cho phép: cout > myObject; ◦ Thay cho: myObject.output(); 25
  26. Nạp chồng <<  Toán tử chèn, << ◦ Sử dụng với cout ◦ Là toán tử hai ngôi  Ví dụ cout << “Hello”; ◦ Toán tử là << ◦ Số hạng thứ nhất là đối tượng cout được định nghĩa trước trong thư viện iostream ◦ Số hạng thứ hai là xâu ký tự “Hello” 26
  27. Nạp chồng <<  Các toán hạng của << ◦ Đối tượng cout, thuộc kiểu lớp ostream ◦ Kiểu lớp của chúng ta  Nhắc lại lớp Money ◦ Sử dụng hàm thành viên output() ◦ Sẽ đẹp hơn nếu có thể sử dụng toán tử <<: Money amount(100); cout << "I have " << amount << endl; thay cho: cout << "I have "; amount.output() 27
  28. Nạp chồng <<  Money amount(100); cout << amount; ◦ << nên trả về giá trị nào đó ◦ Cho phép lồng nhau: cout << "I have " << amount; (cout << "I have ") << amount; ◦ Đối tượng cout  Trả về kiểu đối số thứ nhất của nó, ostream 28
  29. Ví dụ nạp chồng > 29
  30. Ví dụ nạp chồng > 30
  31. Ví dụ nạp chồng > 31
  32. Ví dụ nạp chồng > 32
  33. Ví dụ nạp chồng > 33
  34. Toán tử gán, =  Phải được nạp chồng như toán tử thành viên  Được nạp chồng tự động ◦ Toán tử gán mặc định  Sao chép thông minh thành viên  Các biến thành viên từ một đối tượng tương ứng với các biến thành viên từ một đối tượng khác  Mặc định cho các lớp đơn giản ◦ Nhưng với các con trỏ phải tự viết 34
  35. Tăng và giảm  Mỗi toán tử có hai phiên bản ◦ Ký hiệu tiền tố: ++x; ◦ Ký hiệu hậu tố: x++;  Phải phân biệt khi nạp chồng ◦ Phương pháp nạp chồng chuẩn tiền tố ◦ Thêm tham số thứ hai kiểu int hậu tố  Chỉ để đánh dấu giúp bộ biên dịch  Chỉ rõ hậu tố được cho phép 35
  36. Nạp chồng toán tử mảng, [ ]  Có thể nạp chồng [ ] cho lớp ◦ Để sử dụng với các đối tượng thuộc lớp ◦ Toán tử phải trả về một tham chiếu ◦ Toán tử [ ] phải là một hàm thành viên 36
  37. Tóm tắt  Các toán tử C++ dựng sẵn có thể được nạp chồng  Các toán tử thực ra chỉ là các hàm  Hàm bạn truy cập trực tiếp thành viên private  Các toán tử có thể được nạp chồng như là các hàm thành viên ◦ Số hạng thứ nhất là đối tượng gọi  Hàm bạn giúp tăng hiệu quả ◦ Không cần thiết nếu đã có các hàm truy cập/hàm biến đổi  Tham chiếu đặt tên cho biến bằng một bí danh  Có thể nạp chồng > ◦ Kiểu trả về là một tham chiếu 37