caùch nhaän dieän ñoái töôïng, ta theâm moät vuøng döõ lieäu vaøo lôùp cô sôû ñeå nhaän dieän, vuøng naøy coù giaù trò phuï thuoäc vaøo loaïi cuûa ñoái töôïng vaø ñöôïc goïi laø vuøng [r]
(1)4 Phương thức ảo tính đa 4 Phương thức ảo tính đa
hình hình
1
(2)Nội dung Nội dung 1
1 Bài tốn quản lý danh Bài toán quản lý danh sách đối tượng khác kiểu sách đối tượng khác kiểu 3
3 Phương thức ảoPhương thức ảo 4
4 Phương thức ảo tuýPhương thức ảo tuý
2
4
(3)1 B.toán q.lý đ.tượng khác kiểu 1 B.toán q.lý đ.tượng khác kiểu - Giả sử ta cần quản lý danh sách đối tượng có kiểu
có thể khác nhau, ta cần giải hai vấn đề: Cách lưu trữ thao tác xử lý
- Xét trường hợp cụ thể, đối tượng người, sinh viên cơng nhân
- Về lưu trữ: Ta dùng union, trường hợp
đối tượng phải có kích thước chứa đối tượng có kích
- Về lưu trữ: Ta dùng union, trường hợp
đối tượng phải có kích thước chứa đối tượng có kích thước lớn Điều gây lãng phí khơng gian lưu trữ Một cách thay lưu trữ đối tượng kích thước dùng danh sách (mảng, dslk, ) trỏ để quản lý đối tượng
(4)Dùng vùng chọn kiểu Dùng vùng chọn kiểu
Về lưu trữ: Ta dùng mảng trỏ đến lớp sở
để trỏ đến đối tượng thuộc lớp
Xét lớp Người lớp kế thừa sinh viên công nhân
Thao tác ta quan tâm xuat Ta cần bảo đảm thao tác xuất
(5)Ví dụ minh hoạ Ví dụ minh hoạ
class Nguoi {
protected:
char *HoTen; int NamSinh; public:
Nguoi(char *ht, int ns):NamSinh(ns) {HoTen = strdup(ht);}
strdup(ht);}
~Nguoi() {delete [] HoTen;}
void An() const { cout << HoTen << " an chen com";}
void Ngu() const { cout << HoTen << " ngu tieng";}
void Xuat() const { cout << "Nguoi, ho ten: " << HoTen << " sinh " << NamSinh; }
(6)Ví dụ minh hoạ Ví dụ minh hoạ
class SinhVien : public Nguoi {
protected:
char *MaSo; public:
SinhVien(char *n, char *ms, int ns) : Nguoi(n,ns) { MaSo = strdup(ms);}
~SinhVien() {delete [] MaSo;} ~SinhVien() {delete [] MaSo;}
void Xuat() const { cout << "Sinh vien " << HoTen << ", ma so " << MaSo;}
};
class NuSinh : public SinhVien {
public:
NuSinh(char *ht, char *ms, int ns) : SinhVien(ht,ms,ns) {}
(7)Ví dụ minh hoạ Ví dụ minh hoạ
class CongNhan : public Nguoi {
protected:
double MucLuong; public:
CongNhan(char *n, double ml, int ns) : Nguoi(n,ns), MucLuong(ml) { }
void Xuat() const { cout << "Cong nhan, ten " void Xuat() const { cout << "Cong nhan, ten " << HoTen << " muc luong: " << MucLuong;}
};
void XuatDs(int n, Nguoi *an[]) {
for (int i = 0; i < n; i++) {
(8)Ví dụ minh hoạ Ví dụ minh hoạ
const int N = 4; void main()
{
Nguoi *a[N];
a[0] = new SinhVien("Vien Van Sinh", ”200001234", 1982);
a[1] = new NuSinh("Le Thi Ha Dong", ”200001235", 1984);
a[2] = new CongNhan("Tran Nhan Cong", 1000000, a[2] = new CongNhan("Tran Nhan Cong", 1000000,
1984);
a[3] = new Nguoi("Nguyen Thanh Nhan", 1960); XuatDs(4,a);
(9)Dùng vùng chọn kiểu Dùng vùng chọn kiểu
Xuất liệu cho đoạn chương trình sau:
Nguoi, ho ten: Vien Van Sinh sinh 1982 Nguoi, ho ten: Le Thi Ha Dong sinh 1984 Nguoi, ho ten: Tran Nhan Cong sinh 1984
Nguoi, ho ten: Nguyen Thanh Nhan sinh 1960
Tất đối tượng quan điểm người
thao tác thực thông qua trỏ đến lớp Người thao tác thực thông qua trỏ đến lớp Người
Để bảo đảm xuất liệu tương ứng với đối tượng, phải có
cách nhận diện đối tượng, ta thêm vùng liệu vào lớp sở để nhận diện, vùng có giá trị phụ thuộc vào loại đối tượng gọi vùng chọn kiểu
(10)2 Phương thức ảo 2 Phương thức ảo
Con trỏ thuộc lớp sở trỏ đến lớp con:
Nguoi* pn = new SinhVien(“Le Vien Sinh”, 200001234, 1982);
Ta mong muốn thông qua trỏ thuộc lớp sở
truy xuất hàm thành phần định nghĩa lại lớp con:
pn->Xuat(); // Mong muon: goi Xuat cua lop sinh // vien, thuc te: goi Xuat cua lop // Nguoi
Phương thức ảo cho phép giải vấn đề Ta qui định
một hàm thành phần phương thức ảo cách thêm từ khoá virtual vào trước khai báo hàm
Trong ví dụ trên, ta thêm từ khố virtual vào trước khai
(11)Phương thức ảo Phương thức ảo
class Nguoi {
protected:
char *HoTen; int NamSinh; public:
Nguoi(char *ht, int ns):NamSinh(ns) {HoTen = strdup(ht);}
strdup(ht);}
~Nguoi() {delete [] HoTen;}
void An() const { cout << HoTen << " an chen com";}
void Ngu() const { cout << HoTen << " ngu tieng";}
virtual void Xuat() const { cout << "Nguoi, ho ten: " << HoTen << " sinh " << NamSinh; }
(12)Phương thức ảo Phương thức ảo
class SinhVien : public Nguoi {
protected:
char *MaSo; public:
SinhVien(char *n, char *ms, int ns) : Nguoi(n,ns) { MaSo = strdup(ms);}
~SinhVien() {delete [] MaSo;} ~SinhVien() {delete [] MaSo;}
void Xuat() const { cout << "Sinh vien " << HoTen << ", ma so " << MaSo;}
};
class NuSinh : public SinhVien {
public:
NuSinh(char *ht, char *ms, int ns) : SinhVien(ht,ms,ns) {}
(13)Phương thức ảo Phương thức ảo
class CongNhan : public Nguoi {
protected:
double MucLuong; public:
CongNhan(char *n, double ml, int ns) : Nguoi(n,ns), MucLuong(ml) { }
void Xuat() const { cout << "Cong nhan, ten " void Xuat() const { cout << "Cong nhan, ten " << HoTen << " muc luong: " << MucLuong;}
};
void XuatDs(int n, Nguoi *an[]) {
for (int i = 0; i < n; i++) {
(14)Phương thức ảo Phương thức ảo
const int N = 4; void main()
{
Nguoi *a[N];
a[0] = new SinhVien("Vien Van Sinh", "200001234", 1982);
a[1] = new NuSinh("Le Thi Ha Dong", "200001235", 1984);
"200001235", 1984);
a[2] = new CongNhan("Tran Nhan Cong", 1000000, 1984);
a[3] = new Nguoi("Nguyen Thanh Nhan", 1960); XuatDs(4,a);
}
Phương thức ảo xuat khai báo lớp Nguoi cho phép
(15)Phương thức ảo Phương thức ảo
Nguoi *pn;
pn = new SinhVien("Vien Van Sinh", "200001234", 1982);
pn->Xuat(); // Goi thao tac xuat cua lop Sinh vien
Con trỏ pn thuộc lớp Nguoi trỏ đến đối tượng sinh
viên, pn->Xuat() thực thao tác xuất lớp sinh viên
Trở lại ví dụ trên, i a[i] trỏ đến đối tượng Trở lại ví dụ trên, i a[i] trỏ đến đối tượng
thuộc loại khác nhau, thao tác tương ứng với lớp gọi
Dùng phương thức ảo khắc phục nhược điểm
cách tiếp cận dùng vùng chọn kiểu:
Thao tác đơn giản dùng switch/case khó
(16)Thêm lớp mới Thêm lớp mới
Dùng phương thức ảo, ta dễ dàng nâng cấp sửa chữa Việc
thêm loại đối tượng đơn giản, ta không cần phải sửa đổi thao tác xử lý (hàm XuatDs) Qui trình thêm xây dựng lớp kế thừa từ lớp sở lớp có định nghĩa lại phương thức (ảo) lớp tạo cần
class CaSi : public Nguoi class CaSi : public Nguoi {
protected:
double CatXe; public:
CaSi(char *ht, double cx, int ns) : Nguoi(ht,ns), CatXe(cx) {}
void Xuat() const { cout << "Ca si, " << HoTen << " co cat xe " << CatXe;}
(17)Thêm lớp mới Thêm lớp mới
void XuatDs(int n, Nguoi *an[]) {
for (int i = 0; i < n; i++) {
an[i]->Xuat(); cout << "\n"; }
} }
Hàm XuatDs khơng thay đổi, hoạt động
cho loại đối tượng ca sĩ thuộc lớp đời
Có thể xem thao tác XuatDs viết trước cho
(18)Các lưu ý sử dụng phương thức ảo Các lưu ý sử dụng phương thức ảo
Phương thức ảo hoạt động thông qua trỏ
Muốn hàm trở thành phương thức ảo có hai cách: Khai
báo với từ khoá virtual hàm tương ứng lớp sở phương thức ảo
Phương thức ảo hoạt động hàm lớp sở
lớp có nghi thức giao tiếp giống hệt
Nếu lớp định nghĩa lại phương thức ảo gọi
Nếu lớp định nghĩa lại phương thức ảo gọi
(19)Phương thức huỷ bỏ ảo Phương thức huỷ bỏ ảo
Trong ví dụ quản lý danh sách đối tượng thuộc lớp
Nguoi, SinhVien, CongNhan, … Thao tác dọn dẹp đối tượng cần thiết
const int N = 4; void main()
{
Nguoi *a[N];
a[0] = new SinhVien("Vien Van Sinh", a[0] = new SinhVien("Vien Van Sinh", "20001234", 1982);
a[1] = new NuSinh("Le Thi Ha Dong", "20001235", 1984);
a[2] = new CongNhan("Tran Nan Cong", 1000000, 1984);
a[3] = new Nguoi("Nguyen Thanh Nhan", 1960); XuatDs(4,a);
(20)Phương thức huỷ bỏ ảo Phương thức huỷ bỏ ảo
Thông qua trỏ thuộc lớp sở Nguoi, có phương
thức huỷ bỏ lớp Nguoi gọi
Để bảo đảm việc dọn dẹp đầy đủ, ta dùng phương thức
huỷ bỏ ảo
class Nguoi {
protected: protected:
char *HoTen; int NamSinh; public:
Nguoi(char *ht, int ns):NamSinh(ns) {HoTen = strdup(ht);}
virtual ~Nguoi() {delete [] HoTen;}
virtual void Xuat(ostream &os) const { os << "Nguoi, ho ten: " << HoTen << " sinh " <<
NamSinh; }
(21)3 PT ảo th tuý lớp csở tr tượng 3 PT ảo th tuý lớp csở tr tượng
Lớp sở trừu tượng lớp sở khơng có đối tượng
thuộc Một đối tượng thuộc lớp sở trừu tượng phải thuộc lớp
(22)Khi lớp có phương thức ảo tuý, lớp trở thành lớp
sở trừu tượng Ta tạo đối tượng thuộc lớp sở tuý
Ta định nghĩa phương thức ảo tuý,
có đối tượng thuộc lớp gọi
Phương thức ảo tuý có ý nghĩa cho việc tổ chức sơ đồ
phân cấp lớp, đóng vai trị chừa sẵn chỗ trống cho
Phương thức ảo tuý lớp sở trừu tượng Phương thức ảo tuý lớp sở trừu tượng
(23)Phương thức ảo tuý lớp sở trừu tượng Phương thức ảo tuý lớp sở trừu tượng
Bản thân lớp lớp sở trừu tượng