You are on page 1of 18

CHƯƠNG 6 - TÍNH ĐA

HÌNH (POLYMOPHISM)
• 6.1. Khái niệm kết gán sớm và kết gán muộn
• 6.2. Hàm ảo
• 6.3. Lớp trừu tượng và hàm ảo thuần túy
1. Khái niệm
Kết gán sớm và kết gán muộn
 Khi đối tượng nhận một thông báo thực hiện một
phương thức, hệ thống sẽ:
 Kiểm tra cú pháp của thông báo
 Gắn thông báo đó với 1 định nghĩa hàm cụ thể
Việc kết gán có thể xảy ra ở hai thời điểm:
• Lúc biên dịch chương trình  Kết gán sớm
• Lúc chạy chương trình  Kết gán muộn
2. Phương thức ảo
• Định nghĩa:
• Hàm ảo là hàm thành phần của lớp
• Được khai báo trong lớp cơ sở và định nghĩa lại
trong lớp dẫn xuất
• Cú pháp
virtual <kiểu trả về> <tên hàm>([tham số])
{
//thân hàm
}
• Một số chú ý:
• Định nghĩa các phương thức ảo như các phương
thức thông thường
• Không có hàm khởi tạo ảo nhưng có thể có hàm
huỷ ảo
• Con trỏ của lớp cơ sở có thể chứa địa chỉ của đối
tượng lớp dẫn xuất
• Cơ chế kết gán muộn:
• Khi một lớp có phương thức ảo hoặc lớp cơ sở có
phương thức ảo
• Chương trình dịch sẽ phát sinh thêm một con trỏ
ảo (virtual pointer)
• Con trỏ này trỏ tới một bảng ảo (Vtable)
• Bảng ảo có chứa địa chỉ của các phương thức ảo
• Quá trình phát sinh một đối tượng lớp dẫn xuất:
• B1: xác định các thành phần ( ko ảo) kể cả các
thành phần của lớp cơ sở
• Bước 2: Xây dựng con trỏ ảo và bảng ảo
• Khi kết gán muộn, căn cứ vào con trỏ ảo để xác định phương
thức trong bảng ảo và phương thức của lớp dẫn xuất
• Xây dựng lớp giáo viên và sinh viên kế thừa từ lớp người
NGUOI
{
- ht,namsinh
- nhap, in
- loai(){returrn 0};
}
SV:NGUOI
{
-lop,dtb
-nhap, in
-loai(){ return 1;}
}
GV:NGUOI
{
-hsl, dc
-nhap,in
-loai(){return 2;}
}
Chú ý:
• Cơ chế kết gán phương thức ảo chỉ có thể thực hiện qua
phép gán con trỏ hoặc tham chiếu
NGUOI a,*p;
GV b;
a=b;
a.nhap(); //kết gán sớm
p=&b;
pnhap(); //kết gán muộn
NGUOI &q=b;
qnhap(); //kết gán muộn
void f(NGUOI x)
{ x.nhap(); //kết gán sớm}
void f(NGUOI &x)
{ x.nhap(); //kết gán muộn }
3. Phương thức ảo thuần tuý
• Mục đích:
• Tránh lãng phí bộ nhớ
• Cung cấp một phương thức thống nhất làm giao diện
chung.

• Khai báo:
virtual <kiểu trả về> <tên phương thức>([tham số])=0;
Phương thức ảo thuần tuý
• Đặc điểm:
• Không thể khai báo đối tượng thuộc lớp có phương
thức ảo thuần tuý
• Lớp có phương thức ảo thuần tuý chỉ làm lớp cơ
sở cho lớp khác và gọi là lớp cơ sở trừu tượng
• Lớp dẫn xuất kế thừa lớp cơ sở trừu tượng mà
không định nghĩa lại phương thức ảo thuần tuý 
nó trở thành lớp cơ sở trừu tượng
class Foo { public: void DoSomething() { /* ... */ } };
class Bar : public virtual Foo { public: void
DoSpecific() { /* ... */ } };
class A { public: void Foo() {} }; class B : public A {};
class C : public A {}; class D : public B, public C {};

D d; d.Foo(); // is this B's Foo() or C's Foo() ??


class A { public: void Foo() {} }; class B : public virtual A
{}; class C : public virtual A {}; class D : public B, public
C {};
1. Tính trừu tượng trong C++, cài đặt với từ khóa virtual.
Từ khóa virtual không được đặt ra ngoài lớp
2. Hàm ảo là hàm có từ khóa virtual đặt trước khai báo
hàm
3. Phương thức ảo thuần túy có dạng:
virtual <Kiểu trả về> tên_phương_thức(<tham số>) = 0;
4. Lớp trừu tượng là lớp có chứa các phương thức ảo
thuần túy
5. Không thể tạo ra một đối tượng từ lớp trừu tượng.
6. Bất kỳ lớp dẫn xuất từ một lớp cơ sở trừu tượng phải
định nghĩa lại tất cả các phương thức thuần túy ảo mà nó
thừa hưởng:
        - Bằng các phương thức ảo thuần túy
        - Hoặc những định nghĩa thực sự
Quy tắc về cách gọi các phương thức ảo
Lời gọi phương thức tĩnh Lời gọi phương thức ảo
1. Nếu lời gọi xuất phát từ một đối tượng của lớp nào thì
phương thức của lớp đó sẽ được gọi
2. Nếu lời gọi xuất phát từ một 2. Nếu lời gọi tới phương thức
con trỏ kiểu lớp nào thì ảo từ một con trỏ thì phụ thuộc
phương thức của lớp đó sẽ vào đối tượng cụ thể mà con
được gọi, bất kể con trỏ chứa trỏ đó trỏ tới: con trỏ đang trỏ
địa chỉ của đối tượng nào tới đối tượng của lớp nào thì
phương thức của lớp đó sẽ
được gọi

You might also like