Tính kế thừa-2
Một lớp dẫn xuất có thể định nghĩa lại một hàm thành viên lớp cơ sở. Điều này được gọi là overriding. Khi hàm đó được đề cập bởi tên trong lớp dẫn xuất, phiên bản của lớp dẫn xuất được chọn một cách tự động. Toán tử định phạm vi có thể sử ...
Một lớp dẫn xuất có thể định nghĩa lại một hàm thành viên lớp cơ sở. Điều này được gọi là overriding. Khi hàm đó được đề cập bởi tên trong lớp dẫn xuất, phiên bản của lớp dẫn xuất được chọn một cách tự động. Toán tử định phạm vi có thể sử dụng để truy cập phiên bản của lớp cơ sở từ lớp dẫn xuất.
Ví dụ 5.2: Định nghĩa một hàm thành viên lớp cơ sở trong lớp dẫn xuất và project có tên là CT5_2.PRJ
File EMPLOY.H
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
File EMPLOY.CPP
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
File HOURLY.H
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
File HOURLY.CPP
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
File CT5_2.CPP
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
Chúng ta chạy ví dụ 5.2, kết quả ở hình 5.5

Hình 5.5: Kết quả của ví dụ 5.2
Ví dụ 5.3: Định nghĩa một thành viên dữ liệu của lớp cơ sở trong lớp dẫn xuất.
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
Chúng ta chạy ví dụ 5.3, kết quả ở hình 5.6

Hình 5.6: Kết quả của ví dụ 5.3
Khi dẫn xuất một lớp từ một lớp cơ sở, lớp cơ sở có thể được kế thừa là public, protected và private.
class <drived_class_name> : <type_of_inheritance> <base_class_name>
{
………………..
};
Trong đó type_of_inheritance là public, protected hoặc private. Mặc định là private.
Khi dẫn xuất một lớp từ một lớp cơ sở public, các thành viên public của lớp cơ sở trở thành các thành viên public của lớp dẫn xuất, và các thành viên protected của lớp cơ sở trở thành các thành viên protected của lớp dẫn xuất. Các thành viên private của lớp cơ sở không bao giờ được truy cập trực tiếp từ một lớp dẫn xuất.
Khi dẫn xuất một lớp từ một lớp cơ sở protected, các thành viên public và protected của lớp cơ sở trở thành các thành viên protected của lớp dẫn xuất. Khi dẫn xuất một lớp từ một lớp cơ sở private, các thành viên public và protected của lớp cơ sở trở thành các thành viên private của lớp dẫn xuất.
Bảng sau (hình 5.6)tổng kết khả năng truy cập các thành viên lớp cơ sở trong một lớp dẫn xuất dựa trên thuộc tính xác định truy cập thành viên của các thành viên trong lớp cơ sở và kiểu kế thừa.
Kiểu kế thừa | |||
Kế thừa public | Kế thừa protected | Kế thừa private | |
public | public trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend và các hàm không thành viên. | protected trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend. | private trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend. |
protected | protected trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend. | protected trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend. | private trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend. |
private | Dấu trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend thông qua các hàm thành viên public và protected của lớp cơ sở. | Dấu trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend thông qua các hàm thành viên public và protected của lớp cơ sở. | Dấu trong lớp dẫn xuất.Có thể truy cập trực tiếp bởi các hàm thành viên không tĩnh, các hàm friend thông qua các hàm thành viên public và protected của lớp cơ sở. |
Hình 5.7: Tổng kết khả năng truy cập thành viên lớp cơ sở trong lớp dẫn xuất.
Bởi vì một lớp dẫn xuất kết thừa các thành viên lớp cơ sở của nó (ngoại trừ constructor và destructor), khi một đối tượng của lớp dẫn xuất được khởi động, constructor lớp cơ sở phải được gọi để khởi động các thành viên lớp cơ sở của đối tượng lớp dẫn xuất. Một bộ khởi tạo lớp cơ sở (sử dụng cú pháp giống như bộ khởi tạo thành viên) có thể được cung cấp trong constructor lớp dẫn xuất để gọi tường minh constructor lớp cơ sở, mặt khác constructor lớp dẫn xuất sẽ gọi constructor mặc định lớp cơ sở.
Các constructor lớp cơ sở và các toán tử gán lớp cơ sở không được kế thừa bởi lớp dẫn xuất.Tuy nhiên, các constructor và các toán tử gán lớp dẫn xuất có thể gọi các constructor và các toán tử gán lớp cơ sở.
Một constructor lớp dẫn xuất luôn gọi constructor lớp cơ sở của nó đầu tiên để khởi tạo các thành viên lớp cơ sở của lớp dẫn xuất. Nếu constructor lớp dẫn bị bỏ qua, constructor mặc định lớp dẫn gọi constructor lớp cơ sở. Các destructor được gọi theo thứ tự ngược lại thứ tự gọi các constructor, vì thế destructor lớp dẫn xuất được gọi trước destructor lớp cơ sở của nó.
Ví dụ 5.4: Minh họa thứ tự các contructor và destructor lớp cơ sở và lớp dẫn xuất được gọi và project có tên là CT5_4.PRJ
File POINT.H
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
File POINT.CPP
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
File CIRCLE.H
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
File CIRCLE.CPP
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
File CT5_4.CPP
![]() |
||
![]() ![]() ![]() ![]() |
||
![]() ![]() |
||
![]() |
Chúng ta chạy ví dụ 5.4, kết quả ở hình 5.8

Hình 5.8: Kết quả của ví dụ 5.4