Có thể định nghĩa lại hàm thành viên của lớp cơ sở trong lớp. con[r]
(1)Ngơn ngữ lập trình
Bài 6:
Nạp Chồng Toán Tử và Kế Thừa
Giảng viên: Lê Nguyễn Tuấn Thành Email: thanhlnt@tlu.edu.vn
(2)Nội dung
2
Nạp chồng toán tử (Operator Overloading) Hàm
bạn (Friend Functions)
Kế thừa (Inheritance)
(3)1 Nạp chồng toán tử và Hàm bạn
(4)Mục tiêu
4
Nạp chồng toán tử
Toán tử hai ngơi (binary operators)
Tốn tử ngơi (unary operators)
Nạp chồng hàm thành viên
(5)L
ớp
M
on
(6)Giới thiệu nạp chồng toán tử
6
Những toán tử +,-, %, == etc thực hàm!
Các hàm đặc biệt gọi với cú pháp khác so với
cách gọi hàm thông thường
Gọi hàm thông thường:
Tên_Hàm (Danh_Sách_Đối_Số)
Với tốn tử: ví dụ, x + 7, “+” tốn tử ngơi (binary operator) với x, toán hạng (operands)
Thử viết theo cách gọi hàm thông thường: +(x,7)
“+” tên hàm
x, tham số hàm
(7)Tại dùng nạp chồng toán tử?
Những toán tử xây dựng sẵn
Ví dụ, +, -, = , %, ==, /, *
Đã thao tác với kiểu dựng sẵn C++
Nhưng liệu thực phép + với
đối tượng lớp Money?, giống như: money1 + money2;
Để làm điều này, phải nạp chồng
(8)Cơ nạp chồng
8
Nạp chồng toán tử
Tương tự với nạp chồng hàm
Toán tử thân tên hàm
Ví dụ khai báo
const Money operator + (const Money& amount1, const Money& amount2);
Nạp chồng toán tử + với toán hạng đối tượng kiểu
Money
Giá trị trả lại kiểu Money
Mục đích: cho phép thực phép + hai đối tượng
(9)Nạp chồng toán tử “+”
const Money operator + (const Money& amount1, const Money& amount2);
Chú ý: hàm nạp chồng tốn tử “+” khơng phải hàm thành viên lớp Money
(10)Định nghĩa nạp chồng toán tử “+” cho lớp Money
(11)Nạp chồng toán tử “==”
Toán tử so sánh “==”
Cho phép so sánh đối tượng lớp Money
Khai báo:
bool operator ==(const Money& amount1, const Money& amount2);
(12)Nạp chồng toán tử (Unary operators)
12
Tốn tử ngơi: có tốn hạng
Toán tử phủ định (negation) “-”
X = -Y // đặt X giá trị phủ định Y
Toán tử tăng ++
(13)Nạp chồng toán tử “-” cho lớp Money Khai báo hàm nạp chồng toán tử “-” cho lớp Money
const Money operator –(const Money& amount);
Không phải hàm thành viên lớp
Chú ý: có đối số, tốn tử có tốn hạng
Định nghĩa hàm nạp chồng tốn tử ngơi “-”
const Money operator –(const Money& amount) {
return Money(-amount.getDollars(), -amount.getCents()); }
Trả lại đối tượng vô danh (anonymous object) Lưu ý: nạp chồng tốn tử “-” có hai trường hợp!
Khi tốn tử ngơi, với toán hạng/đối số
(14)Sử dụng nạp chồng toán tử “-”
14
Xét ví dụ sau:
Money amount1(10), amount2(6), amount3; amount3 = amount1 – amount2;
=> Gọi nạp chồng tốn tử ngơi “-”
amount3 = -amount1;
(15)Nạp chồng toán tử hàm thành viên (1/2)
Những ví dụ trước: hàm đứng độc lập khơng phải
thành viên lớp
Có thể nạp chồng “toán tử thành viên”, xem
như hàm thành viên
Khi toán tử hàm thành viên
Chỉ có MỘT tham số, khơng phải có tham số!
(16)Nạp chồng toán tử hàm thành viên (2/2)
16
Ví dụ:
Money cost(1, 50), tax(0, 15), total; total = cost + tax;
Nếu toán tử “+” nạp chồng tốn tử thành
viên thì:
Biến/ đối tượng cost đối tượng gọi hàm nạp chồng Đối tượng tax tham số hàm nạp chồng Tưởng tượng giống cách viết sau
total = cost.+(tax);
Khai báo toán tử “+” định nghĩa lớp
const Money operator +(const Money& amount);
(17)Nạp chồng số toán tử khác
Toán tử gọi hàm: ()
Toán tử &, ||, dấu phẩy
Toán tử gán = (assignment operator), phải nạp
chồng hàm thành viên!
Toán tử tăng, giảm: ++,
Mỗi toán tử có phiên bản:
Tiền tố (prefix notation): ++x; Hậu tố (postfix notation): x++;
Toán tử mảng [ ], nạp chồng hàm thành viên!
(18)Nạp chồng toán tử >> <<
18
Cho phép nhập xuất liệu cho đối tượng
Tăng tính dễ đọc cho chương trình
Ví dụ viết:
cout << myObject; cin >> myObject;
Thay phải viết:
(19)Toán tử chèn << (1/2) (Insertion operator)
Được sử dụng với cout, ví dụ: cout << "Hello";
Là tốn tử hai ngơi:
Tốn hạng đối tượng định nghĩa sẵn cout, từ thư viện iostream
Toán hạng thứ hai liệu/đối tượng cần in hình
Giả sử khai báo: Money amount(100);
Nếu nạp chồng toán tử << với lớp Money,
chúng ta viết:
cout << "I have " << amount << endl;
thay sử dụng hàm thành viên output() viết:
(20)Toán tử chèn << (2/2) (Insertion operator)
20
Nạp chồng << nên trả giá trị
Giá trị trả về?
Đối tượng cout !
Trả kiểu đối số đầu tiên, ostream
Hai cách viết sau tương đương:
(21)(22)Chương trình nạp chồng tốn tử << >> (2/5)
(23)(24)Chương trình nạp chồng toán tử << >> (4/5)
(25)(26)Hàm bạn
(Friend functions)
26
Nhớ lại:
Nạp chồng tốn tử khơng phải hàm thành viên
Khi đó, truy xuất liệu phải thơng qua hàm accessor
mutator
Cách làm khơng hiệu (tăng phụ phí gọi hàm này!)
Hàm bạn Không phải hàm thành viên lớp có
thể truy xuất trực tiếp đến liệu khu vực
private lớp
Khơng có phụ phí gọi hàm => hiệu
Vì vậy: cách tốt cài đặt nạp chồng toán tử khai
báo chúng hàm bạn
(27)Lớp bạn
(Friend classes)
Tồn lớp bạn lớp khác
Tương tự hàm bạn lớp
Nếu lớp F bạn lớp C => tất hàm thành viên
của lớp F bạn lớp C
Điều ngược lại khơng
(28)Tóm tắt nạp chồng toán tử hàm bạn
28
Những tốn tử dựng sẵn (built-in) C++
được nạp chồng để thao tác với đối tượng lớp mà bạn định nghĩa
Toán tử thực hàm!
Tốn tử nạp chồng hàm ngồi (khơng
phải thành viên) hàm thành viên lớp
Toán hạng đối tượng gọi
Hàm bạn truy xuất trực tiếp thành viên
(29)2 Kế thừa
(30)Mục tiêu
30
Cơ kế thừa (inheritance)
Lớp thừa kế (derived classes), với hàm tạo
Khu vực Protected
Định nghĩa lại hàm thành viên
Hàm không kế thừa
Chương trình với kế thừa
Tốn tử gán hàm tạo
(31)Giới thiệu kế thừa
Thế kế thừa? Định nghĩa?
Một kỹ thuật lập trình mạnh, khái niệm trừu tượng
Cấu trúc tổng quát khái niệm định nghĩa
trong lớp (lớp cha / lớp sở)
Những phiên chuyên biệt (lớp con) sau kế thừa thuộc tính lớp tổng qt
(32)Cơ kế thừa
32
Một lớp kế thừa từ lớp khác
Lớp sở (lớp cha)
Lớp tổng quát mà từ lớp khác kế thừa
Lớp thừa kế (lớp con)
Một lớp
Tự động có hàm/biến thành viên lớp sở Sau thêm hàm/biến thành viên
Thuật ngữ (terminology) kế thừa giống quan hệ
gia đình
Lớp cha (Parent class) ~ Lớp sở (Base class)
Lớp (Child class) ~ Lớp thừa kế (Derived class) Lớp tổ tiên (Ancestor class)
(33)Lớp thừa kế
(Derived classes)
Xét ví dụ lớp Nhân_Viên (Employee)
Có thể bao gồm nhiều loại nhỏ:
Nhân viên trả lương (Salaried employees)
Nhân viên bán thời gian, theo (Hourly employees)
…
Khái niệm tổng quát Nhân_Viên hữu ích! Được định
nghĩa trước khung chung:
Tất nhân viên có thơng tin chung như: Tên, Tuổi,
Giới Tính, Quốc Tịch, CMTND
(34)Định nghĩa lại hàm thành viên
34
Xét hàm printCheck() lớp sở Nhân_Viên
Được định nghĩa lại lớp thừa kế
Do loại nhân viên khác có kiểm tra
(35)(36)Giao diện cho lớp thừa kế HourlyEmployee (2/2)
(37)Giao diện lớp HourlyEmployee Lưu ý phần đầu chương trình
Cấu trúc #ifndef
Khai báo bao gồm (include) thư viện liên quan Khai báo bao gồm lớp sở employee.h!
Khai báo cấu trúc kế thừa
class HourlyEmployee : public Employee
Giao diện (interface) lớp thừa kế liệt kê thành
viên định nghĩa lại
Bởi tất thành viên khác kế thừa từ lớp sở
định nghĩa trước đó!
Lớp HourlyEmployee thêm thành viên sau:
Hàm khởi tạo
(38)Định nghĩa lại hàm thành viên trong lớp HourlyEmployee
38
Lớp HourlyEmployee định nghĩa lại:
Hàm thành viên printCheck() lớp sở
Phiên hàm printCheck() “ghi đè” (overrides) phiên
bản cũ cài đặt lớp sở Employee
Cài đặt hàm thành viên phải thực
lớp HourlyEmployee
Định nghĩa lại hàm khác nạp chồng hàm nào?
Rất khác
Định nghĩa lại hàm lớp thừa kế
CÙNG danh sách tham số
Thực chất viết lại hàm
Nạp chồng hàm
Danh sách tham số khác
(39)Truy xuất hàm định nghĩa lại
Khi định nghĩa lại hàm lớp con, định
nghĩa hàm lớp sở không bị đi!
Employee JaneE;
HourlyEmployee SallyH;
JaneE.printCheck(); //gọi hàm printCheck lớp Employee
SallyH.printCheck(); //gọi hàm printCheck lớp HourlyEmployee
(40)Hàm tạo lớp thừa kế (1/2)
40
Hàm tạo lớp sở không kế thừa tự động
trong lớp !
Nhưng chúng gọi bên hàm tạo của lớp con!
Hàm tạo lớp sở nên khởi tạo tất biến
thành viên
Xét ví dụ hàm tạo lớp HourlyEmployee
HourlyEmployee::HourlyEmployee(string theName, string theNumber, double theWageRate, double theHours)
: Employee(theName, theNumber),
(41)Hàm tạo lớp thừa kế (2/2)
Nếu lớp không gọi hàm tạo lớp sở:
Hàm tạo mặc định lớp sở tự động gọi
Ví dụ:
(42)Lưu ý: liệu private lớp sở
42
Lớp kế thừa biến thành viên khu vực private
Nhưng truy xuất trực tiếp “theo tên” (by-name) đến biến thành viên
Ngay truy xuất biến private thông qua hàm thành viên lớp con!
Biến thành viên private CHỈ truy xuất “theo
(43)Lưu ý: hàm thành viên private lớp sở
Không thể truy xuất bên giao diện cài đặt
của lớp sở
(44)Khu vực protected
44
Một khu vực cho thành viên lớp
Cho phép truy xuất “theo tên” thành viên lớp thừa
kế
Nhưng không cho phép truy xuất lớp không kế thừa!
Trong lớp mà thành viên protected định
(45)Đa kế thừa
(Multiple inheritance)
Lớp kế thừa nhiều lớp sở!
Cú pháp: lớp sở phân tách dấu phẩy
Ví dụ:
(46)Bài tập
46
Định nghĩa lớp Nhân viên (Employee)
Private: Tên, Tuổi, Giới Tính, Quốc Tịch
Public: void printCheck()
Protected: CMTND
Định nghĩa hai lớp kế thừa từ lớp Nhân_Viên
Nhân viên trả lương (SalariedEmployee)
Nhân viên bán thời gian, theo (HourlyEmployee)
(47)Tóm tắt kế thừa
Kế thừa cho phép sử dụng lại code
Cho phép lớp kế thừa từ lớp khác thêm chức
Lớp kế thừa thành viên lớp sở
thêm thành viên
Biến thành viên private lớp sở truy
xuất “theo tên” lớp
Hàm thành viên private không kế thừa, sử
dụng riêng lớp sở
Có thể định nghĩa lại hàm thành viên lớp sở lớp
con
Các lớp khác có định nghĩa khác
Thành viên khu vực protected lớp sở
(48)Giáo trình Tham khảo
48
Giáo trình chính: W Savitch, Absolute C++, Addison Wesley, 2002
Tham khảo:
A Ford and T Teorey, Practical Debugging in C++, Prentice Hall, 2002