Professional Documents
Culture Documents
Chương 4 - Overloading
Chương 4 - Overloading
Chương 4 - Overloading
và hàm
Chỉ thị c=a+b; trong ví dụ trên được chương trình dịch hiểu là c=a.operator+(b);
Hàm toán tử cũng có thể trả về kiểu void khi ảnh hưởng chỉ tác động lên một trong các
toán hạng tham gia biểu thức. Ví dụ phương thức đảo dấu số phức sau:
Với cách cài đặt như trên, khi thực hiện phép tính c = - a + b; sẽ gây lỗi vì –a có kiểu trả
về là void, ta chỉ nên sử dụng –a; đứng riêng lẻ.
Đậu Anh Tú _ Cpp
4.3 Khả năng và giới hạn của overload
Ký hiệu đứng sau từ khoá operator phải là một trong số các ký hiệu toán tử áp dụng cho
các kiểu dữ liệu cơ sở, không thể dùng các ký hiệu mới. Các toán tử không thể định
nghĩa chồng :
o Toán tử truy nhập thành phần “.” (chấm)
o Toán tử định phạm vi “::”
o Toán tử ba ngôi “?:”
o Toán tử lấy kích thước “sizeof()”
Khi định nghĩa chồng toán tử, phải tuân theo nguyên tắc là Một trong số các toán hạng
phải là đối tượng. Nói cách khác, hàm toán tử phải:
o Đối với toán tử có tham số đầu tiên là đối tượng, ta thường định nghĩa nó như là phương thức
của class.
o Đối với toán tử có các tham số khác nhau về kiểu dữ liệu, ta định nghĩa thông qua hàm friend
Hơn nữa, mỗi hàm toán tử chỉ có thể áp dụng với kiểu toán hạng nhất định; cần chú ý rằng các
tính chất vốn có, chẳng hạn tính giao hoán của toán tử không thể áp dụng một cách tuỳ tiện cho
các toán tử được định nghĩa chồng.
Chú ý kiểu tham số int là tham số giả định để xác định dạng tiền tố hay hậu tố, khi thực
hiện phép toán thực tế không cần phải truyền tham số.
Chỉ sử dụng trả về tham chiếu với dạng tiền tố, còn đối với dạng hậu tố, khi định nghĩa
cần thực hiện tạo 1 biến tạm để nhận giá trị trước khi tăng, sau đấy tăng this lên và trả về
biến tạm.
Nhờ giá trị trả về của hàm operator[] là tham chiếu đến một thành phần toạ độ của vùng nhớ
động nên ta có thể đọc/ghi các thành phần toạ độ của mỗi đối tượng Vector. Như vậy có thể sử
dụng các đối tượng Vector giống như các biến mảng.
Có thể cải tiến hàm toán tử operator[] bằng cách bổ sung thêm phần kiểm tra tràn chỉ số hoặc chỉ
số âm.
Ví dụ :
Nhận xét:
Khi đã nạp chồng new, delete cục bộ, ta vẫn có thể gọi được các toán tử new và delete
toàn cục thông qua toán tử phạm vi.
Các toán tử new và delete là các phương thức static của các lớp bởi vì chúng không có
tham số ngầm định.
Bài tập, xây dựng 2 class Matrix{}, và class Vector{} như sau:
Trong đấy class Matrix{} chứa 2 biến n,m lần lượt là 2 chiều của ma trận, con trỏ cấp 2 **v
dùng để quản lý các phần tử của ma trận.
Trong đấy class Vector{} chứa biến n là độ dài Vector , con trỏ *v dùng để quản lý các phần tử
của Vector.
Xây dựng các phương thức khởi tạo, phương thức huỷ, nạp chồng toán tử nhập, xuất, và phép
Đậu Anh Tú _ Cpp
nhân giữa Matrix và Vector.
Phép nhân ma trận véc tơ
Việc chuyển đổi từ kiểu dữ liệu lớn sang kiểu dữ liệu bé hơn sẽ gây ra 1 số kết quả không
mong muốn (tràn số, mất 1 phần giá trị …)
Các kiểu class không thể thoải mái chuyển sang các kiểu khác được mà phải do lập trình
viên tự định nghĩa. Có khá nhiều trường hợp class cần phải ép kiểu (gán đối tượng bằng
1 kiểu dữ liệu khác, ép đối tượng sang 1 kiểu dữ liệu khác, chuyển kiểu trong biểu thức
….)
Tuỳ theo từng trường hợp, ta sẽ xây dựng các cách thức ép kiểu khác nhau: phương thức
khởi tạo (constructor), nạp chồng phép gán, nạp chồng phép ép kiểu hoặc xây dựng
phương thức, hàm tự do cụ thể cho việc ép kiểu.
Chú ý nếu chúng ta sử dụng constructor khởi tạo có truyền tham số mặc định thì có thể
sẽ gây ra lỗi “ambiguous”
Đậu Anh Tú _ Cpp
4.6.3.Chuyển đổi kiểu dữ liệu bằng Constructor
Chú ý, không xây dựng cả 2 phép chuyển đổi kiểu dữ liệu vì sẽ gây ra lỗi “ambiguous”
trong biểu thức (biểu thức chứa cả 2 toán hạng có 2 kiểu dữ liệu thì sẽ không xác định
được nên ưu tiên ép sang kiểu dữ liệu nào).
Các phép toán sinh ra một giá trị mới nên trả về một giá trị (thay vì tham chiếu) và nên
để kiểu const (để kết quả ấy không thể bị sửa đổi). Ví dụ:
Trong cách dùng trên, đầu tiên chúng ta gọi Constructor khởi tạo để tạo đối tượng c (dòng 2),
sau đấy gọi copy constructor để tạo bản sao cho giá trị trả về của hàm (dòng 5), và gọi
destructor để huỷ đối tượng c khi ra khỏi hàm.
Khi trình biên dịch gặp đoạn mã này, nó hiểu đối tượng được tạo chỉ nhằm mục
đích làm giá trị trả về, nên nó tạo thẳng một đối tượng bên ngoài (để trả về) - bỏ
qua việc tạo và huỷ đối tượng bên trong lời gọi hàm. Và chỉ có một lời gọi duy
nhất đến constructor của Complex (không phải copy constructor) thay vì dãy lời
gọi trước.
Đây là quá trình tối ưu hoá giá trị trả về