
1
Chương 8:
THỪA KẾ ẢO-TÍNH ĐA HÌNH
Giáo viên: Võ Hồng Bảo Châu
Khoa CNTT trường ĐH Lạc Hồng
LẬP TRÌNH
HƯỚNG ĐỐI TƯỢNG
MỤC TIÊUMỤC TIÊU
Giới thiệu khái niệm thừa kế ảo, hàm ảo
Tính đa hình trong lập trình hướng đối tượng
2OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
NỘI DUNG CHI TIẾTNỘI DUNG CHI TIẾT
•TÍNH ĐA HÌNH
•OVERLOADED VÀ OVERRIDDEN
•LIÊN KẾT TĨNH
•LIÊN KẾT ĐỘNG
•HÀM ẢO
•THỪA KẾ ẢO
3OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
Tính Đa Hình(Polymorphism) Tính Đa Hình(Polymorphism)
•Đa hình: “nhiều hình thức”, hành động cùng tên có thể
được thực hiện khác nhau đối với các đối tượng/các lớp
khác nhau.
•Ngữ cảnh khác kết quả khác
Đường Thẳng Hình TrònĐiểm Hình Vuông
Vẽ
4OOP-CHƯƠNG 8-TÍNH ĐA HÌNH

2
TÍNH ĐA HÌNHTÍNH ĐA HÌNH
•Khả năng có những hiện thực khác nhau cho cùng một
hành vi
•Kỹ thuật cho phép thay đổi nội dung của cùng 1 hành vi
trong 2 lớp cha – con
•Bản chất: Sửa code của cùng 1 hành vi ở 2 lớp cha con để
code này khác nhau
•Đa hình tạo ra khả năng cho phép gọi một hành vi của một
lớp mà không cần quan tâm đến hiện thực của hành vi này.
5OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
VÍ DỤ VỀ TÍNH ĐA HÌNHVÍ DỤ VỀ TÍNH ĐA HÌNH
class Người
void DiChuyển();
class ĐànÔng
void DiChuyển();
class ĐànBà
void DiChuyển();
class SHAPE
void Draw ()
{
}
class CIRCLE
int x,y,r;
void Draw ()
{ circle (x,y,r);
}
class RECTANGLE
int x1,y1, x2, y2;
void Draw ()
{ rectangle(x1,y1, x2, y2);
}
class TRIANGLE
int x1,y1, x2, y2 , x3, y3;
void Draw ()
{ line(x1,y1, x2, y2);
line(x2,y2, x3, y3);
line(x3,y3, x1, y1);
}
Đa hình tạo được tính mềm dẻo/linh động
của chương trình
6OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
OVERLOADED VÀ OVERRIDDENOVERLOADED VÀ OVERRIDDEN
•Overloaded methods:
– Nhằm cung cấp các dạng khác nhau của hành vi (danh sách tham
số khác nhau), nhưng vẫn có cùng tên gọi trong cùng một lớp.
•Overridden methods:
– Hiện thực lại hành vi đã có của tổ tiên
– Phải có cùng tên và trùng mọi yếu tố tạo nên hành vi này.
7OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
LIÊN KẾT TĨNHLIÊN KẾT TĨNH
•Liên kết tĩnh (static binding):
– Xác định khi biên dịch chương trình.
– Dùng hàm thành viên.
– Gọi hàm của lớp cơ sở (lớp cha).
class ContactDirContactDir {
//...
public:
int Lookup (const char
*name);
//...
};
class SortedDirSortedDir : public ContactDir {
public:
SortedDir(const int max) : ContactDir(max)
{}
int Lookup(const char *name);
};
void main() {
ContactDir c1(10);
SortedDir *p; p = &c1;
cout<<p->Lookup(“ABC”);
….
}
Gọi hàm Gọi hàm
nào ?nào ?
8OOP-CHƯƠNG 8-TÍNH ĐA HÌNH

3
LIÊN KẾT ĐỘNGLIÊN KẾT ĐỘNG
•Liên kết động (dynamic binding)
– Xác định khi thực thi chương trình.
– Dùng hàm ảo (virtual function).
– Gọi hàm của lớp dẫn xuất (lớp con).
– Thể hiện tính đa hình của OOP.
class ContactDirContactDir {
//...
public:
virtual int Lookup (const char *name);
};
class SortedDirSortedDir : public ContactDir {
//….
public:
int Lookup(const char *name);
};
void main() {
ContactDir c1(10);
SortedDir *p1; p1 = &c1;
cout<<p->Lookup(“ABC”);
SortedDir c2(20);
ContactDir *p2; p2 = &c2;
cout<<p->Lookup(“ABC”);
}
Gọi hàm Gọi hàm
của lớp của lớp
nào ?nào ?
9OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
HÀM ẢOHÀM ẢO
Xem kết qủa của việc khái quát hóa sau:
class ANIMAL
void Travel();
class Bird
void Travel()
class Fish
void Travel()
class Snake
void Travel()
Bạn có hình dung
nổi một ANIMAL di
chuyển như thế
nào không?
Bạn có hình dung nổi
một đối tượng thuộc các
lớp này di chuyển như
thế nào không?
Không
Dùng hàm ảo
Có cụ thể
10 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
HÀM ẢOHÀM ẢO
•Là kết qủa của việc khái quát hóa qúa cao đến nỗi
không biết viết code thế nào.
•Là những hành vi chỉ khai báo mà không viết code.
Để dành code cụ thể sẽ được hiện thực ở các lớp
dẫn xuất ( lớp cụ thể hơn).
•Tư duy tự nhiên:
– Từ các đối tượng cụ thể hàm cụ thể.
– Từ các lớp cụ thể có cùng tính chất hàm ảo.
11 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
KHAI BÁO HÀM ẢOKHAI BÁO HÀM ẢO
•Cú pháp:
•Class Tên lớp
•{
•…
•public:
•virtual Tên hàm ảo () { }
•…
•}
12 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH

4
VÍ DỤVÍ DỤ
Động cơ
Nhiên liệu
Động cơ xăng
Nhiên liệu Động cơ diezel
Nhiên liệu
Động cơ 2 thì
Nhiên liệu Động cơ 4 thì
Nhiên liệu
13 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
Class DongCo{
public:
virtual void NhienLieu(){ };
}
Class DongCoXang{
public:
void NhienLieu(){
cout<<“Dùng xăng hoặc xăng pha nhớt”; }
}
Class DongCoDiezel{
public:
void NhienLieu(){
cout<<“Dùng dầu Diezel”;}
}
Class DongCo2Thi{
public:
void NhienLieu(){
cout<<“Dùng xăng pha nhớt”;}
}
Class DongCo4Thi{
public:
void NhienLieu(){
cout<<“Dùng xăng”;}
}
void main(){
DongCo *obj;
DongCo2Thi 2t;
DongCo4Thi 4t;
DongCoXang x;
DongCoDiezel d;
for(int i=0;i<4;i++)
{
switch(i){
case 0: obj=&x;break;
case 1: obj=&d;break;
case 2: obj=&2t;break;
case 3: obj=&4t;break;}
obj->NhienLieu();}
}
Kết quả
in ra là
gì?
14 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
PHÂN LOẠI PHƯƠNG THỨC ẢOPHÂN LOẠI PHƯƠNG THỨC ẢO
•Phương thức ảo rỗng
– Khai báo nhưng không làm gì
– Dùng tạo sự liên kết động trong hệ thống lớp kế thừa.
– Có thể khai báo đối tượng thuộc lớp có phương thức ảo rỗng và
gởi thông điệp đến đối tượng đó.
Ví dụ: DongCo obj; obj.NhienLieu();
•Phương thức ảo thuần
– Lớp chứa phương thức này được gọi là lớp trừu tượng.
– Không thể khai báo đối tượng thuộc lớp này cũng như không thể
gởi thông điệp đến phương thức ảo thuần.
Class A{
public :
virtual void NhienLieu()=0;
}
15 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
VÍ DỤ HÀM ẢO – TÍNH ĐA HÌNHVÍ DỤ HÀM ẢO – TÍNH ĐA HÌNH
HÀM ẢO
GIÁ THÀNH
Dữ liệu: đơn giá
Phương thức:
+giá thành
+diện tích
+trị giá
HÌNH TRÒN
Dữ liệu: bán kính
Phương thức:
+khởi tạo
+diện tích
HÌNH CHỮ NHẬT
Dữ liệu: dài, rộng
Phương thức:
+khởi tạo
+diện tích
16 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH

5
class GIATHANH{
protected: float dongia;
public:
giathanh (float c){ dongia=c);};
virtual dientich(){ }
float trigia() { return dientich()*dongia;}
}
class HINHTRON: public GIATHANH{
float bk;
public:
HINHTRON(float r, float c):
GIATHANH(c){
bk=r;}
float dientich(){
return bk*bk*M_PI;}
};
class HINHCN: public GIATHANH{
float dai,rong;
public:
HINHCN(float d,float r, float c):
GIATHANH(c){
dai=d;rong=r;}
float dientich(){ return dai*rong;}
};
void main(){
HINHTRON a(5,1000);
HINHCN b(2,4,2000);
cout<<“Tri gia hinh tron:<<a.trigia()<<endl;
cout<<“Tri gia hcn:”<<b.trigia()<<endl;
getch();
}
Nếu không khai báo hàm
dientich là hàm ảo thì kết
quả chương trình là gì?
17 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
THỪA KẾ ẢOTHỪA KẾ ẢO
class A
class B class C
class D
18 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
Ví dụVí dụ
class A{
int dulieu;
//...
};
class B: public A{};
class C: public A{};
class D: public B, public C{
//...
};
D thừa kế A
“2 lần”
D có 2 thành phần
dữ liệu và 2 thành
phần hành vi
Dư thừa dữ liệu
=?
19 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH
Giải quyếtGiải quyết
•Để tránh tình trạng một thành phần trong lớp A xuất hiện 2
lần trong lớp D, sử dụng thừa kế ảo
class B: virtual public A{};
class C: virtual public A{};
class D: public B, public C{
//...
};
20 OOP-CHƯƠNG 8-TÍNH ĐA HÌNH