Download as pdf or txt
Download as pdf or txt
You are on page 1of 40

ĐẠI HỌC KINH TẾ KỸ THUẬT CÔNG NGHIỆP

KHOA CÔNG NGHỆ THÔNG TIN

LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG

CHƯƠNG 4.
KỸ THUẬT KẾ THỪA

Năm học 2021 - 2022 1


MỤC ĐÍCH CỦA CHƯƠNG

Nội dung tập trung trình bày các vấn đề về kỹ thuật


kế thừa trong lập trình hướng đối tượng trên C++
như:

• Khái niệm kế thừa, cách định nghĩa các lớp trong


mối quan hệ kế thừa, phạm vi truy xuất các thành phần
trong kế thừa.

• Hiểu và phân loại được các dạng kế thừa: đơn kế


thừa, đa kế thừa.

2
CÁC NỘI DUNG CHÍNH

4.1. Đơn kế thừa

4.2. Đa kế thừa

4.3. Các lớp cơ sở ảo

3
GIỚI THIỆU
Thừa kế là một kỹ thuật quan trọng trong lập trình hướng đối tượng. Kỹ
thuật này cho phép lập trình viên sử dụng lại mã lệnh chương trình. Từ đó giúp
làm giảm thời gian và công sức cần thiết để phát triển chương trình đồng thời
tăng sức tin cậy của chương trình đó

 Kế thừa cho phép các lớp được xây dựng từ các lớp khác đã có

 Một lớp được xây dựng kế thừa một lớp khác gọi là lớp dẫn xuất (derived
class).

 Lớp dùng để xây dựng lớp dẫn xuất gọi là lớp cơ sở (base class).

4
GIỚI THIỆU
Lớp dẫn xuất sẽ kế thừa:

 Các thành phần (dữ liệu, hàm) của lớp cơ sở;

 Đồng thời bổ sung các thành phần mới.

Lớp nào trong chương trình cũng có thể là một lớp cơ sở hay cụ thể hơn
một lớp dẫn xuất có thể là lớp cơ sở cho một lớp khác

5
GIỚI THIỆU
Một số sơ đồ minh họa tính kế thừa

Động vật
point

coloredpoint Động vật có vú Loài bò sát

Ngựa Chó Thằn lằn Rắn

6
GIỚI THIỆU
Một số sơ đồ minh họa tính kế thừa

Công dân

Cán bộ giảng dạy Cán bộ quản lý

Trưỏng bộ môn

7
GIỚI THIỆU
Tính kế thừa và đặc trưng của lớp kế thừa
Lớp cơ sở
Đặc trưng A
Các đặc trưng này
Đặc trưng B được định nghĩa ở
Đặc trưng C lớp cơ sở

Lớp kế thừa Đặc trưng này được


Đặc trưng A định nghĩa ở lớp kế
Đặc trưng B thừa
Đặc trưng C
Đặc trưng D
8
4.1. ĐƠN KẾ THỪA
Khái niệm:
Một lớp dẫn xuất chỉ kế thừa từ một lớp cơ sở gọi là đơn kế thừa
Cú pháp khai báo đơn kế thừa:

class <Tên_lớp_cơ_sở>
{
// Nội dung lớp cơ sở
};
class <Tên_lớp_dẫn_xuất> : Kiểu_thừa_kế <Tên_lớp_cơ_sở>
{
//Nội dung lớp dẫn xuất
};
9
4.1. ĐƠN KẾ THỪA

Trong đó:
Kiểu_thừa_kế có thể là:
 public
 private
 protected
Kiểu thừa kế chỉ rõ các thành phần của lớp cơ sở sẽ được kế
thừa theo cách nào.
Nếu được bỏ trống chương trình ngầm hiểu là private.

10
4.1. ĐƠN KẾ THỪA
Ví dụ

11
4.1. ĐƠN KẾ THỪA
class Box
{
float hight, weight;
public:
Lớp cơ sở
void Set()
{
cout<<"\n Input hight: "; cin>> hight;
cout<<"\n Input weight: "; cin>> weight;
}
void Display()
{
cout<<"hight = "<<hight<<"\tweight= "<<weight<<endl;
}
};
12
4.1. ĐƠN KẾ THỪA
class ColorBox: public Box
{ int color;
Lớp dẫn
public: xuất
void SetColor()
{ Set();
cout<<"\n Input color: "; cin>>color;
}
void DisplayColor()
{
Display();
cout<<"color= "<<color<<endl;
}
}; 13
4.1. ĐƠN KẾ THỪA
main()

{ Box a;

ColorBox b;

cout<<"\n - Input Box a:"<<endl; a.Set();

cout<<"\n - Output Box a:"<<endl; a.Display();

cout<<"\n - Input ColorBox b:"<<endl;

b.SetColor();

cout<<"\n - Output ColorBox b:"<<endl;

b.DisplayColor();

b.Display(); /* Gọi hàm Display kế thừa từ lớp Box để in ra hight và weight*/

14
}
4.1. ĐƠN KẾ THỪA

Mỗi đối tượng lớp dẫn xuất ColorBox gồm:

 Thành phần dữ liệu và hàm mà lớp Box có

 Bổ sung thêm các thành phần riêng.

15
4.1. ĐƠN KẾ THỪA
Chú ý:
 Trong C++ không phải mọi hàm thành phần đều có thể truyền qua tính kế
thừa. Cụ thể một số trường hợp sau đây không cho phép sử dụng tính kế
thừa.
• Hàm tạo.
• Hàm hủy.
• Các toán tử mới do người dùng định nghĩa.
• Các toán tử gán do người dùng định nghĩa
• Quan hệ friend.

16
4.1. ĐƠN KẾ THỪA
Chú ý:
 Lớp dẫn xuất không được phép truy nhập đến thành phần private của lớp
cơ sở.
 Được phép khai báo bên trong lớp dẫn xuất các thành phần cùng tên với các
thành phần đã có trong lớp cơ sở.
<Hai thành phần cùng tên này có thể cùng kiểu hay khác kiểu. Lúc này bên trong một đối tượng của
lớp dẫn xuất có tới hai thành phần khác nhau có cùng tên, nhưng trong phạm vi lớp dẫn xuất tên chung
đó nhằm chỉ định thành phần được khai báo lại trong lớp dẫn xuất.>

Khi muốn chỉ định thành phần cùng tên trong lớp cơ sở, phải sử dụng
tên lớp cơ sở và toán tử phạm vi :: đặt trước tên thành phần đó với cú pháp:
<Tên_lớp_cơ_sở> :: <Tên_thành_phần>
 Trong trường hợp chương trình sử dụng nhiều mức độ kế thừa khác nhau, toán
tử phạm vi vẫn cho phép truy nhập đến bất kể thành phần của lớp cơ sở nào.
17
4.1. ĐƠN KẾ THỪA
Ghi đè hàm thành phần của lớp cơ sở
 Một lớp dẫn xuất có thể ghi đè hàm (overriding function) thành phần lớp cơ
sở. Hàm ghi đè và hàm bị ghi đè giống hệt nhau về tên, tham số và giá trị
trả về, chúng chỉ khác nhau ở vị trí, một hàm đặt trong lớp dẫn xuất và hàm
kia thì có mặt trong lớp cơ sở.

 Một đối tượng lớp dẫn xuất gọi đến hàm ghi đè hoặc khi hàm đó được gọi
trong lớp dẫn xuất, hàm ghi đè của lớp dẫn xuất được gọi một cách tự
động. Muốn gọi đến hàm đó ở lớp cơ sở cần sử dụng toán tử định phạm
vi :: đặt trước tên hàm.

 Ví dụ: Tạo lớp điểm trên mặt phẳng point có thành phần dữ liệu x,y. Lớp
điểm màu coloredpoint kế thừa từ lớp point và bổ sung thành phần màu
color:
18
4.1. ĐƠN KẾ THỪA
class point
{ float x,y;
public:
void Set(int a, int b)
{ x=a; y=b; }
void display()
{ cout<<"Toa do : "<<x<<" "<<y<<endl;}
};
class coloredpoint : public point
{ unsigned int color;
public:
void SetColor(int mau)
{ color= mau;}
void display() /* Ghi đè hàm display() của lớp cơ sở*/
{point::display(); /*gọi tới hàm cùng tên trong lớp cơ sở*/
cout<<"Mau "<<color<<endl;}
19
4.1. ĐƠN KẾ THỪA
main()

coloredpoint n ;

n.Set(4,5);

n.SetColor(6);

cout<<"Diem mau n \n";

n.display();/*Gọi tới hàm của lớp dẫn xuất coloredpoint */

cout<<"Chi hien thi toa do cua n\n";

n.point::display(); /* Gọi tới hàm của lớp cơ sở point */

} 20
4.1. ĐƠN KẾ THỪA
 Hàm tạo và hàm hủy trong kế thừa

Hàm tạo: Cú pháp định nghĩa hàm tạo lớp dẫn xuất:

Hàmtạolớpdẫnxuất(Dsthamsố) : Hàmtạolớpcơsở(Dsthamsố)

// Nội dung hàm tạo lớp dẫn xuất

21
4.1. ĐƠN KẾ THỪA
 Hàm tạo và hàm hủy trong kế thừa

Hàm tạo: Quy tắc định nghĩa hàm tạo lớp dẫn xuất như sau:

- Nếu lớp cơ sở và lớp dẫn xuất không định nghĩa hàm tạo thì hàm tạo
ngầm định của hai lớp sẽ đươc gọi theo đúng thứ tự.

- Nếu lớp cơ sở và lớp dẫn xuất có định nghĩa hàm tạo thì khi định nghĩa
hàm tạo lớp dẫn xuất luôn mô tả một lời gọi tới một trong các hàm tạo
tương ứng ở lớp cơ sở.

+ Hàm tạo không tham số của lớp dẫn xuất có thể có hoặc không cần
mô tả lại một lời gọi đến hàm tạo không tham số lớp cơ sở.

+ Hàm tạo có tham số của lớp dẫn xuất cần thiết phải mô tả lại một
lời gọi đến hàm tạo có tham số lớp cơ sở tương ứng. 22
4.1. ĐƠN KẾ THỪA
 Hàm tạo và hàm hủy trong kế thừa

Hàm hủy: Hàm hủy thứ tự gọi ngược lại với hàm tạo. Khi hủy đối tượng
hàm hủy lớp dẫn xuất được gọi trước, rồi đến hàm hủy lớp cơ sở.

23
4.1. ĐƠN KẾ THỪA
 Hàm tạo và hàm hủy trong kế thừa

Nhận xét:

 Hàm tạo không được kế thừa.

 Nếu muốn sử dụng hàm tạo không tham số của lớp cơ sở thì có thể
không cần mô tả cùng với định nghĩa của hàm tạo lớp dẫn xuất

 Các tham số mà hàm tạo lớp dẫn xuất truyền cho hàm tạo lớp cơ sở
không nhất thiết lấy nguyên si từ các tham số nó nhận được mà có thể
được thay đổi đi ít nhiều.

 Nếu lớp có thành phần dữ liệu con trỏ phải định nghĩa hàm hủy ngược lại
không bắt buộc.
24
4.1. ĐƠN KẾ THỪA
 Hàm tạo và hàm hủy trong kế thừa

Hàm tạo sao chép:

 Nếu trong lớp dẫn xuất không khai báo tường minh hàm tạo sao chép, thì
công việc này được chương trình biên dịch đảm nhiệm nhờ định nghĩa hàm
tạo sao chép ngầm định.

 Về nguyên tắc, trong định nghĩa của hàm tạo sao chép lớp dẫn xuất có
thể mô tả bất kỳ hàm tạo sao chép hoặc hàm tạo nào có mặt trong lớp cơ
sở. Lớp có thành phần dữ liệu con trỏ phải định nghĩa hàm tạo sao chép,
ngược lại không bắt buộc.

 Ví dụ: 4.3 <Tài liệu học tập>

25
4.1. ĐƠN KẾ THỪA
 Con trỏ và kế thừa

• Tương thích giữa đối tượng thuộc lớp dẫn xuất với đối tượng
thuộc lớp cơ sở:

 Một đối tượng của lớp dẫn xuất có thể thay thế một đối tượng của lớp cơ
sở. Nghĩa là tất cả các thành phần của lớp cơ sở đều tìm thấy trong lớp
dẫn xuất.

 Một đối tượng lớp cơ sở không thể thay thế một đối tượng lớp dẫn xuất.

 Ví dụ: 4.5 <Tài liệu học tập>

26
4.1. ĐƠN KẾ THỪA
 Con trỏ và kế thừa

• Tương thích giữa con trỏ lớp dẫn xuất và con trỏ lớp cơ sở :

 Một con trỏ đối tượng lớp cơ sở có thể trỏ đến một đối tượng lớp dẫn
xuất.

 Một con trỏ lớp dẫn xuất không thể trỏ đến đối tượng lớp cơ sở trừ
trường hợp ép kiểu.

 Ví dụ: 4.6 <Tài liệu học tập>

27
4.1. ĐƠN KẾ THỪA
 Con trỏ và kế thừa

• Tương thích giữa tham chiếu lớp dẫn xuất và tham chiếu lớp cơ
sở :

 Một tham chiếu đối tượng lớp cơ sở có thể tham chiếu đến một đối
tượng lớp dẫn xuất.

 Một tham chiếu lớp dẫn xuất không thể tham chiếu đến đối tượng lớp cơ
sở trừ trường hợp ép kiểu.

 Ví dụ: 4.7 <Tài liệu học tập>

28
4.1. ĐƠN KẾ THỪA
 Phạm vi truy xuất

• Khi thiết lập quan hệ kế thừa, vẫn cần phải quan tâm đến tính đóng gói
và che dấu thông tin. Vì vậy cần xác định ảnh hưởng của kế thừa đến phạm
vi truy xuất các thành phần của lớp. Hai vấn đề được đặt ra là:

- Hàm thành phần của lớp dẫn xuất có quyền truy xuất các thành phần
riêng tư của lớp cơ sở hay không.

- Các thành phần của lớp cơ sở, sau khi kế thừa xuống lớp dẫn xuất, thì
bên ngoài có quyền truy xuất đến các thành phần này thông qua đối tượng
của lớp dẫn xuất hay không.

29
4.1. ĐƠN KẾ THỪA
 Phạm vi truy xuất

• Truy xuất các thành phần của lớp cơ sở từ lớp dẫn xuất

- Thành phần public: có thể được truy xuất từ bất cứ nơi nào (từ sau khai
báo lớp).

- Thành phần private: chỉ được truy xuất bởi các hàm thành phần và các
hàm friend của lớp cơ sở. <“Phạm vi lớp” chỉ mở rộng cho “bạn bè”, mà
không được mở rộng đến các lớp “con cháu”>

- Thành phần protected: Thành phần kiểu protected giống như private,
ngoại trừ một điều là các thành phần này có thể được truy nhập từ lớp dẫn
xuất. <Đặc biệt cần chú ý là các thành phần protected không thể truy nhập
từ bên ngoài lớp cơ sở hay lớp dẫn xuất từ lớp cơ sở đó>.
30
4.1. ĐƠN KẾ THỪA
 Phạm vi truy xuất

• Nhận xét:

- Thuộc tính protected là phương tiện để tránh phải sửa đổi lớp cơ sở khi
có lớp dẫn xuất mới ra đời. Nhờ đó nó bảo đảm được tính đóng của một
lớp. Khai báo một thành phần nào có thuộc tính protected tương đương với
qui định trước tất cả các lớp con, cháu sau này đều là bạn của thành phần
đó.

- Thông thường ta dùng thuộc tính protected cho các thành phần dữ liệu
và thuộc tính public cho hàm thành phần.

31
4.1. ĐƠN KẾ THỪA
 Phạm vi truy xuất

• Tổng kết khả năng truy nhập các thành phần trong một lớp:

Truy cập public protected private

Trong cùng lớp Có Có Có

Lớp kế thừa Có Có Không

Bên ngoài lớp Có Không Không


32
4.1. ĐƠN KẾ THỪA
Các kiểu kế thừa

• Khả năng truy nhập các thành phần trong một lớp:

33
4.1. ĐƠN KẾ THỪA
Các kiểu kế thừa

• Kiểu kế thừa private:

- Lớp dẫn xuất kế thừa private từ lớp cơ sở thì


các thành phần protected và public của lớp cơ sở
trở thành private của lớp dẫn xuất. Nói cách khác
mọi thao tác của lớp cơ sở đều bị lớp con che
dấu.

- Dẫn xuất private được sử dụng trong một số


tình huống đặc biệt khi lớp dẫn xuất không khai
báo thêm các thành phần hàm mới mà chỉ định
nghĩa lại các phương thức đã có trong lớp cơ sở.
34
4.1. ĐƠN KẾ THỪA

Các kiểu kế thừa

• Kiểu kế thừa protected:

- Các thành phần public,


protected trong lớp cơ sở trở
thành các thành phần protected
trong lớp dẫn xuất.

35
4.1. ĐƠN KẾ THỪA

 Các kiểu kế thừa

• Kiểu kế thừa public:

- Lớp dẫn xuất kế thừa public từ lớp cơ


sở thì các thành phần protected của lớp
cơ sở trở thành protected của lớp dẫn
xuất, các thành phần public của lớp cơ
sở trở thành public của lớp dẫn xuất.

- Trong dẫn xuất public, các thành


phần, các hàm bạn và các đối tượng của
lớp dẫn xuất không thể truy nhập đến các
thành phần private của lớp cơ sở
36
TÓM TẮT NỘI DUNG
Đơn kế thừa

- Các khái niệm, cách khai báo và sử dụng tính kế thừa.

- Cách cài đặt một số hàm đặc biệt trong lớp như hàm tạo, hàm
tạo sao chép, hàm hủy,….

37
CÂU HỎI CUỐI CHƯƠNG
Câu 1: Giải thích sự khác nhau giữa các thành phần protected và private?

Câu 2: Hàm tạo và hàm hủy hoạt động như thế nào trong lớp kế thừa?

Câu 4: Tìm lỗi sai của đoạn chương trình sau đây
class A
{ public:
void func();
};
class B: private A
{};
main()
{ A a;
B b;
a.func();
b.func();
A *pA= &b;
B *pb= &a;
38
}
BÀI TẬP
Bài tập 1: Xây dựng lớp Người gồm có các thành phần Họ tên và Năm
sinh. Viết các phương thức của lớp như nhập, hiển thị dữ liệu.

Xây dựng lớp Thí sinh kế thừa lớp này, trong lớp Thí sinh có Số báo
danh và Điểm các môn toán, lý, hóa. Hãy xây dựng thêm các phương thức
nhập, xuất và khai báo mảng có kiểu là Thisinh để quản lý danh sách các thí
sinh. Viết chương trình với các công việc sau:

- Nhập vào một danh sách có n thí sinh

- Hiển thị danh sách thí sinh có tổng điểm ba môn tăng dần;

- Tìm một thí sinh khi biết Số báo danh.

- Thống kê xem có bao nhiêu phần trăm thí sinh đạt yêu cầu (cả ba môn
có điểm lớn hơn hoặc bằng 5). 39
BÀI TẬP
Bài tập 2:
Xây dựng lớp Sản phẩm bao gồm: Mã sản phẩm, Tên sản
phẩm, Năm sản xuất và các phương thức nhập, xuất.
Xây dựng tiếp lớp Tivi có thêm các thuộc tính Chiều dài, Chiều
rộng của màn hình. Hãy xây dựng phương thức tính diện tích của
màn hình của lớp Tivi.
Viết chương trình nhập vào các đối tượng của lớp Tivi, sau đó
sắp xếp tăng dần theo diện tích màn hình của các đối tượng này

40

You might also like