Professional Documents
Culture Documents
Return Class
Return Class
Như đã nói, chính vì không thể nào động đến một cách trực tiếp các biến của class nên ta buộc
phải thông qua các hàm để cài đặt giá trị (set) cho biến hoặc lấy giá trị của biến ra để sử dụng
(get) hoặc xem. Nói cách khác, các hàm này chính là chìa khóa để giải mã class.
Thông thường thì các hàm này sẽ được đặt tên phức tạp (như password) chứ không đơn giản là
get, set (vì chìa khóa mà đơn giản thì còn ý nghĩa gì). Tuy nhiên ở đây các bạn chỉ đang học và
làm quen với class cơ bản nên sẽ đặt là get, set cho nhanh.
ví dụ :
Vậy giờ chúng ta sẽ viết thêm 2 hàm getten() và setten()
để lấy giá trị hoặc gán giá trị cho biến ten trong class sv
Lưu ý :
phải có từ khóa public: thì các hàm
getten() vơi setten() mới có thể được
gọi ra trong hàm main. Các bạn
nên tự thử lại trên upcoder nhưng không có từ khóa
public: để xem chuyện gì sẽ xảy ra.
Luyện Tập :
Tự viết lại class trên và thêm các hàm get set với các biến năm sinh hoặc điểm. Sau đó dùng các
hàm này nhập năm sinh và điểm cho các biến trên.
b) Phương thức khởi tạo
Khởi tạo là gì ?
Khởi tạo có nghĩa là tạo ra những giá trị ban đầu cho các biến (thuộc tính) nằm bên trong class
mà không cần phải dùng hàm gán hay bất cứ phương thức nào khác.
Ví dụ : Khi bạn khai báo: int t; trong hàm main thì giá trị của t sẽ khá bất định và không thể biết
trước bằng bao nhiêu.
Chúng ta có thể thấy biến t nhận các giá trị ngẫu nhiên bất kỳ, điều này khá bất tiện. Để cố định
giá trị của t thì ta thường lúc khai báo ta sẽ gán t cho một giá trị nào đó chúng ta muốn bằng các
câu lệnh như int t=0; int t=10 vv
Và vì kiểu int là kiểu dữ liệu cơ bản và chúng ta không thể nào thay đổi phương thức hoạt động
của nó nên chúng ta buộc phải chấp nhận điều này.
Nhưng class lại là thế giới của chúng ta, ta tạo ra class do đó ta có toàn quyền quyết định đối
với nó. Vì vậy chúng ta sẽ tạo ra một kiểu dữ liệu mà chỉ cần khai báo thôi là biến của nó sẽ
được nhận các giá trị mặc định thay vì giá trị ngẫu nhiên bất kỳ hay còn gọi là giá trị rác.
Cấu trúc của phương thức khởi tạo:
Có tên trùng với tên class
<class name>(có hoặc không có tham số)
{ //khối lệnh}
Ví dụ chúng ta tạo ra một kiểu dữ liệu phân số và chúng ta muốn mặc định tử của phân số này
phải bằng 0 và mẫu của nó bằng 1. Ta sẽ làm như sau:
Dễ thấy mặc dù chúng ta không động chạm Tất nhiên chúng ta cũng có thể cho tử bằng
gì đến biến a tuy nhiên các giá trị tử mẫu của a 3 mẫu bằng 8 hay bất cứ giá trị nào khác
đã mang sẵn giá trị mặc định
Luyện tập
Viết lại class trên, thêm các hàm nhập xuất và set tử mẫu. Sau đó dùng hàm nhập để nhập vào
giá trị cho tử mẫu của biến a sau đó dùng hàm xuất hoặc get tử mẫu để xuất các giá trị vừa nhập
ra màn hình theo định dạng phân số (tu/mau).
Phương thức khởi tạo như trên được gọi là khởi tạo mặc định.
Ngoài ra chúng ta còn có phương thức khởi tạo có tham số.
Ví dụ sẽ dễ hiểu hơn mọi lời diễn giải:
Tương tự muốn tạo ra một phân số có tử =10, mẫu bằng 6 thì cũng chỉ cần khai báo
phanso a(10,6);
Và ngoài ra chúng ta sẽ có phương thức khởi tạo sao chép như sau:
Phân số b dù chưa được nhập gì nhưng vẫn xuất ra được 7/9 vì đã sao chép từ phân số d trước
đó đã được nhập 2 giá trị này.
c) Một số ví dụ về hàm cơ bản trong class
Cộng phân số :
So sánh bằng nhau giữa hai phân số
Hàm rút gọn
Trước tiên ta cần xây dựng một hàm tìm ước chung lớn nhất giữa 2 số nguyên.
Có nhiều cách, tuy nhiên ở đây tôi chọn cách dùng giải thuật Euclid bằng đệ quy.
Rồi sau đó rút gọn phân số bằng cách cho cả tử và mẫu chi cho ước chung lớn nhất của chúng
Luyện tập :
Đến giờ thì các bạn có thể làm tất cả các bài về
Do đó chúng ta cần tự định nghĩa lại theo ý chúng ta. Và vì là theo ý chúng ta nên chúng ta
muốn sao cũng được. Ví dụ chúng ta muốn toán tử + của kiểu dữ liệu thitheo sẽ chẳng làm gì cả
ngoài việc xuất ra màn hình câu “Tôi ăn thịt heo” thì ta sẽ thao tác như sau :
Rồi bây giờ chúng ta sẽ bắt đầu định nghĩa nghiêm túc một chút. Giả sử đề bài sẽ yêu cầu các
bạn khi cộng hai biến thitheo thì cần trả về kiểu dữ liệu thitheo nhưng biến kg của kết quả sẽ
mang giá trị tổng của hai biến được cộng và biến gia thì thành trung bình cộng của hai biến kể
trên ta sẽ thao tác như sau :
Tới đây tôi sẽ nói rõ về cách truyền tham số trong quá tải toán tử đối với class.
Thực chất thì quá tải cũng chính là một hàm, nhưng khi bạn muốn dùng hàm thông thường thì
bạn gọi tên hàm ra truyền các tham số (nếu có) vào, thì đối với quá tải toán tử các bạn chỉ cần
viết toán tử ra và cũng truyền tham số vào, tuy nhiên tham số trong quá tải toán tử sẽ ở dạng
ngôi chứ không được truyền trong dấu () như đối với hàm.
ví dụ toán tử nhân (+) khi bạn muốn dùng thì bạn sẽ viết như sau : a + b
Lúc này a và b chính là 2 ngôi và đóng vai trò như 2 tham số được truyền vào hàm quá tải cộng.
Vậy a sẽ được truyền vào đâu và b sẽ được truyền vào đâu ? Ta sẽ đi vào ví dụ để làm rõ hơn.
Ví dụ :
Để tránh nhầm lẫn tôi sẽ viết lại hàm quá tải cộng như sau : từ dòng 11 đến 16 (hình trái)
Ở dòng 22 khi chúng ta viết “a +” thì đây chính là hành vi gọi hàm quá tải (nó tương tự khi ta
viết “a.tong(b)” trong gọi hàm thông thường, “a.tong” trong tình huống này chính là gọi hàm
tong() trong a ra).
Quay lại “a +”, khi gọi lệnh này thì toán tử + sẽ chui vào bên trong a và thực hiện các lệnh của
hàm operator + bên trong a (dòng 11). Lúc này tham số x sẽ nhận giá trị của b (x sao chép giá
trị của b).
Và vì là đang bên trong a nên các biến kg, gia (được tô vàng) chính là của a. Nói cách khác, các
biến này chính là a.kg và a.gia, tuy nhiên do đang bên trong sẵn nên ko cần viết rõ.
Sau khi thực hiện xong các lệnh thì hàm quá tải + sẽ trả về kiểu dữ liệu thitheo. Và cũng như tất
cả các hàm khác, ta cũng có thể đối xử với quá tải như 1 hàm bằng cách thứ 2 (hình bên phải)
Trực tiếp dùng dấu chấm (.) để xuất luôn chứ không cần thông qua biến c như hình bên trái:
Đến đây có lẽ các bạn đã hiểu tại sao quá tải bên trong class thì số tham số sẽ bằng số ngôi giảm
đi một rồi chứ. Nếu vẫn không hiểu thì trời cứu :))
Tôi sẽ ví dụ thêm một vài cách quá tải khác để các bạn đỡ bỡ ngỡ sau này :
Tôi muốn quá tải toán tử nhân cho class thitheo tuy nhiên trị trả về là số nguyên và là tổng của
giá hai loại thịt, ta sẽ làm như sau :
Hoặc tôi muốn quá tải phép trừ giữa kiểu dữ liệu thitheo với một số thực và kết quả trả về là
kiểu dữ liệu thitheo nhưng biến kg sẽ bị trừ đi một lượng bằng số thực kia.
Hoặc quá tải toán tử chia giữa kiểu dữ liệu thitheo và số nguyên nhưng trả về một số thực là kết
quả phép chia giữa biến kg và số nguyên kia :
Luyện tập :
1/ Để kiểm tra khả năng hiểu bài . Các bạn cần trả lời câu hỏi sau : Trong các ví dụ về quá tải
phía trên, tại sao đôi khi tôi dùng hàm xuat() để xuất và đôi khi lại dùng cout để xuất ?
2/Tạo một class sv có các thuộc tính (biến) ten (string), diemtoan (float), diemvan (float).
Xây dựng các hàm nhập xuất.
a) Quá tải toán tử cộng trả về kiểu dữ liệu sv, biến ten sẽ mang tên của ai có diemtoan cao hơn
trong hai biến thành phần, biến diemtoan và điểm văn cũng sẽ lấy giá trị của biến có điểm toán
cao hơn.
b)Quá tải toán tử trừ trả về kiểu dữ liệu sv như câu a, tuy nhiên thay vì so điểm toán thì lần này
chúng ta so điểm văn.
c) Quá tải toán tử nhân trả về kiểu số thực, là trung bình cộng của điểm toán từ hai biến thành
phần.
d) Quá tải toán tử chia trả về kiểu string là tên của người có thứ tự từ điển nhỏ hơn.
e) Xuất tên người có điểm toán cao nhất (sử dụng toán tử +).
f ) Xuất tên người có điểm văn cao nhất (Sử dụng toán tử -).
g) Xuất trung bình cộng điểm toán của 2 bạn có điểm toán và văn cao nhất kể trên.
h) Xuất tên của người có thứ tự từ điển nhỏ nhất.
Input nhập không biết trước số lượng nhiều dòng, mỗi dòng gồm thông tin tên (không khoảng
trắng) điểm toán, điểm văn cách nhau bởi khoảng trắng.
Output như các yêu cầu kể trên, xuất kết quả trên nhiều dòng.
Kể từ sau file này nếu đã thực hành tất cả các bài tập của những file trước thì các bạn bây giờ có
thể làm mọi bài tập của OOP trên upcoder cho đến chương quá tải. Và ngược lại nếu các bạn
chỉ đọc mà không thực hành thì chẳng ai cứu nổi các bạn.
Chúc các bạn may mắn!