Bài giảng Lập trình hướng đối tượng - Chương 6: Kế thừa

pdf 70 trang phuongnguyen 2721
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Lập trình hướng đối tượng - Chương 6: Kế thừa", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfbai_giang_lap_trinh_huong_doi_tuong_chuong_6_ke_thua.pdf

Nội dung text: Bài giảng Lập trình hướng đối tượng - Chương 6: Kế thừa

  1. CHƯƠNG 6. KẾ THỪA ThS. Trần Anh Dũng
  2. Nội dung 1 Quan hệ giữa các lớp đối tượng 2 Kế thừa 3 Kế thừa đơn 4 Phạm vi truy xuất trong kế thừa 55 Đa kế thừa 14/09/2014 Lập trình hướng đối tượng 2
  3. Quan hệ giữa các lớp đối tượng Giữa các lớp đối tượng có những loại quan hệ sau: . Quan hệ một một (1-1) . Quan hệ một nhiều (1-n) . Quan hệ nhiều nhiều (n-n) . Quan hệ đặc biệt hóa, tổng quát hóa 14/09/2014 Lập trình hướng đối tượng 3
  4. Quan hệ một một (1-1) Khái niệm: Hai lớp đối tượng được gọi là có quan hệ một-một với nhau khi một đối tượng thuộc lớp này quan hệ với một đối tượng thuộc lớp kia và một đối tượng thuộc lớp kia có quan hệ duy nhất với một đối tượng thuộc lớp này. Ký hiệu: Quan hệ ClassA ClassB 14/09/2014 Lập trình hướng đối tượng 4
  5. Quan hệ một một (1-1) Ví dụ: Chủ nhiệm LOPHOC GIAOVIEN Hôn nhân VO CHONG Có COUNTRY CAPITAL 14/09/2014 Lập trình hướng đối tượng 5
  6. Quan hệ một nhiều (1-n) Khái niệm: Hai lớp đối tượng được gọi là có quan hệ một-nhiều với nhau khi một đối tượng thuộc lớp này quan hệ với nhiều đối tượng thuộc lớp kia và một đối tượng lớp kia có quan hệ duy nhất với một đối tượng thuộc lớp này. Kí hiệu: Quan hệ ClassA ClassB 14/09/2014 Lập trình hướng đối tượng 6
  7. Quan hệ một nhiều (1-n) Ví dụ: Có LOPHOC HOCSINH Có CONGTY NHANVIEN Sáng tác HOASI TACPHAM 14/09/2014 Lập trình hướng đối tượng 7
  8. Quan hệ nhiều nhiều (n-n) Khái niệm: hai lớp đối tượng được gọi là quan hệ nhiều-nhiều với nhau khi một đối tượng thuộc lớp này có quan hệ với nhiều đối tượng thuộc lớp kia và một đối tượng lớp kia cũng có quan hệ với nhiều đối tượng thuộc lớp này. Kí hiệu Quan hệ ClassA ClassB 14/09/2014 Lập trình hướng đối tượng 8
  9. Quan hệ nhiều nhiều (n-n) Ví dụ Yêu NAM NU Khám bệnh BACSI BENHNHAN 14/09/2014 Lập trình hướng đối tượng 9
  10. Quan hệ đặc biệt hóa – tổng quát hóa Khái niệm: hai lớp đối tượng được gọi là có quan hệ đặc biệt hóa-tổng quát hóa với nhau khi lớp đối tượng này là trường hợp đặc biệt của lớp đối tượng kia và lớp đối tượng kia là trường hợp tổng quát của lớp đối tượng này. ClassA Kí kiệu: ClassB 14/09/2014 Lập trình hướng đối tượng 10
  11. Quan hệ đặc biệt hóa – tổng quát hóa Ví dụ: TAMGIAC NGUOI TAMGIACCAN SINHVIEN 14/09/2014 Lập trình hướng đối tượng 11
  12. Quan hệ đặc biệt hóa – tổng quát hóa Polygon Rectangle Triangle Animal TerrestrialAnimal AquaticAnimal Cat Horse Chicken Fish Octopus 14/09/2014 Lập trình hướng đối tượng 12
  13. Kế thừa Kế thừa là một đặc điểm của ngôn ngữ dùng để biểu diễn mối quan hệ đặc biệt hóa – tổng quát hóa giữa các lớp. Các lớp được trừu tượng hóa và được tổ chức thành một sơ đồ phân cấp lớp. Sự kế thừa là một mức cao hơn của trừu tượng hóa, cung cấp một cơ chế gom chung các lớp có liên quan với nhau thành một mức khái quát hóa đặc trưng cho toàn bộ các lớp nói trên. 14/09/2014 Lập trình hướng đối tượng 13
  14. Kế thừa Các lớp với các đặc điểm tương tự nhau có thể được tổ chức thành một sơ đồ phân cấp kế thừa (cây kế thừa). Quan hệ “là 1”: Kế thừa được sử dụng thông dụng nhất để biểu diễn quan hệ “là 1”. . Một sinh viên là một người . Một hình tròn là một hình ellipse . Một tam giác là một đa giác . 14/09/2014 Lập trình hướng đối tượng 14
  15. Lợi ích kế thừa Kế thừa cho phép xây dựng lớp mới từ lớp đã có. Kế thừa cho phép tổ chức các lớp chia sẻ mã chương trình chung, nhờ vậy có thể dễ dàng sửa chữa, nâng cấp hệ thống. Trong C++, kế thừa còn định nghĩa sự tương thích, nhờ đó ta có cơ chế chuyển kiểu tự động. 14/09/2014 Lập trình hướng đối tượng 15
  16. Đặc tính Kế thừa Cho phép định nghĩa lớp mới từ lớp đã có. . Lớp mới gọi là lớp con (subclass) hay lớp dẫn xuất (derived class) . Lớp đã có gọi là lớp cha (superclass) hay lớp cơ sở (base class). 14/09/2014 Lập trình hướng đối tượng 16
  17. Đặc tính Kế thừa Thừa kế cho phép: . Nhiều lớp có thể dẫn xuất từ một lớp cơ sở . Một lớp có thể là dẫn xuất của nhiều lớp cơ sở Thừa kế không chỉ giới hạn ở một mức: Một lớp dẫn xuất có thể là lớp cơ sở cho các lớp dẫn xuất khác Animal TerrestrialAnimal AquaticAnimal Cat Horse Chicken Fish Octopus 14/09/2014 Lập trình hướng đối tượng 17
  18. Cú pháp khai báo kế thừa class SuperClass{ //Thành phần của lớp cơ sở }; class DerivedClass : public/protected/private SusperClass{ //Thành phần bổ sung của lớp dẫn xuất }; 14/09/2014 Lập trình hướng đối tượng 18
  19. Truy cập thành viên của lớp 14/09/2014 Lập trình hướng đối tượng 19
  20. Kế thừa đơn Xét hai khái niệm Người và Sinh viên với mối quan hệ tự nhiên: Một Sinh viên là một Người. Trong C++, ta có thể biểu diễn khái niệm trên, một sinh viên là một người có thêm một số thông tin và một số thao tác (riêng biệt của sinh viên). Như vậy, ta tổ chức lớp Sinh viên kế thừa từ lớp Người. 14/09/2014 Lập trình hướng đối tượng 20
  21. Kế thừa đơn Ta có thể tổ chức hai lớp Nam sinh và Nữ sinh là hai lớp con (lớp dẫn xuất) của lớp Sinh viên. Trường hợp này, lớp Sinh viên trở thành lớp cha (lớp cơ sở) của hai lớp trên. NGƯỜI GIẢNG VIÊN SINH VIÊN NAM SINH NỮ SINH 14/09/2014 Lập trình hướng đối tượng 21
  22. Kế thừa đơn – Ví dụ class Nguoi { char *HoTen; int NamSinh; public: Nguoi(); Nguoi( char *ht, int ns):NamSinh(ns) {HoTen=strdup(ht);} ~Nguoi() {delete [ ] HoTen;} void An() const { cout<<HoTen<<" an 3 chen com \n";} void Ngu() const { cout<<HoTen<< " ngu ngay 8 tieng \n";} void Xuat() const; friend ostream& operator << (ostream &os, Nguoi& p); }; 14/09/2014 Lập trình hướng đối tượng 22
  23. Kế thừa đơn – Ví dụ class SinhVien : public Nguoi { char *MaSo; public: SinhVien(); SinhVien( char *ht, char *ms, int ns) : Nguoi(ht,ns) { MaSo = strdup(ms); } ~SinhVien() { delete [ ] MaSo; } void Xuat() const; }; 14/09/2014 Lập trình hướng đối tượng 23
  24. Kế thừa đơn – Ví dụ void Nguoi::Xuat() const { cout << "Nguoi, ho ten: " << HoTen; cout << " sinh " << NamSinh; cout << endl; } void SinhVien::Xuat() const { cout << "Sinh vien, ma so: " << MaSo; //cout << ", ho ten: " << HoTen; //cout << ", nam sinh: " << NamSinh; cout << endl; } 14/09/2014 Lập trình hướng đối tượng 24
  25. Kế thừa đơn – Ví dụ void main() { Nguoi p1("Le Van Nhan",1980); SinhVien s1("Vo Vien Sinh", "200002541",1984); cout << "1.\n"; p1.An(); s1.An(); cout << "2.\n"; p1.Xuat(); s1.Xuat(); s1.Nguoi::Xuat(); cout << "3.\n"; cout << p1 << "\n"; cout << s1 << "\n"; } 14/09/2014 Lập trình hướng đối tượng 25
  26. Kế thừa đặc tính của lớp cha Khai báo class SinhVien : public Nguoi { // }; . Cho biết lớp Sinh viên kế thừa từ lớp Người. Khi đó Sinh viên thừa hưởng các đặc tính của lớp Người. Về mặt dữ liệu: Mỗi đối tượng Sinh viên tự động có thành phần dữ liệu họ tên, năm sinh của người. 14/09/2014 Lập trình hướng đối tượng 26
  27. Kế thừa đặc tính của lớp cha Về mặt thao tác: Lớp Sinh viên được tự động kế thừa các thao tác của lớp cha. Đây chính là khả năng sử dụng lại mã chương trình. Riêng phương thức thiết lập không được kế thừa. Khả năng thừa hưởng các thao tác của lớp cơ sở có thể được truyền qua “vô hạn mức”. 14/09/2014 Lập trình hướng đối tượng 27
  28. Định nghĩa lại thao tác ở lớp con Ta có thể định nghĩa lại các đặc tính ở lớp con đã có ở lớp cha, việc định nghĩa chủ yếu là thao tác. class SinhVien : public Nguoi { char *MaSo; public: // void Xuat() const; }; void SinhVien::Xuat() const { cout << "Sinh vien, ma so: " << MaSo << ", ho ten: " << HoTen; } 14/09/2014 Lập trình hướng đối tượng 28
  29. Ràng buộc ngữ nghĩa ở lớp con Có thể áp dụng quan hệ kế thừa mang ý nghĩa ràng buộc, đối tượng ở lớp con là đối tượng ở lớp cha nhưng có dữ liệu bị ràng buộc: . Hình tròn là Ellipse với ràng buộc bán kính ngang dọc bằng nhau. . Số ảo là số phức với ràng buộc phần ảo bằng 0 . Lớp số ảo sau đây là một ví dụ minh họa. 14/09/2014 Lập trình hướng đối tượng 29
  30. Ví dụ class Complex { friend ostream& operator <<(ostream&, Complex); friend class Imag; double re, im; public: Complex( double r = 0, double i = 0):re(r), im(i){ } Complex operator +(Complex b); Complex operator -(Complex b); Complex operator *(Complex b); Complex operator /(Complex b); double Norm() const { return sqrt(re*re + im*im);} }; 14/09/2014 Lập trình hướng đối tượng 30
  31. Ví dụ class Imag: public Complex { public: Imag(double i = 0):Complex(0, i){ } Imag(const Complex &c) : Complex(0, c.im){ } Imag& operator = (const Complex &c){ re = 0; im = c.im; return *this; } double Norm() const { return fabs(im); } }; 14/09/2014 Lập trình hướng đối tượng 31
  32. Ví dụ void main() { Imag i = 1; Complex z1(1,1) Complex z3 = z1 - i; // z3 = (1,0) i = Complex(5,2); // i la so ao (0,2) Imag j = z1; // j la so ao (0,1) cout << "z1 = " << z1 << "\n"; cout << "i = " << i << "\n"; cout << "j = " << j << "\n"; } 14/09/2014 Lập trình hướng đối tượng 32
  33. Ràng buộc ngữ nghĩa ở lớp con Trong ví dụ trên, lớp số ảo (Imag) kế thừa hầu hết các thao tác của lớp số phức (Complex). Tuy nhiên, ta muốn ràng buộc mọi đối tượng thuộc lớp số ảo đều phải có phần thực bằng 0. Vì vậy, phải định nghĩa lại các hàm thành phần có thể vi phạm điều này. Ví dụ phép toán gán phải được định nghĩa lại để đảm bảo ràng buộc này. 14/09/2014 Lập trình hướng đối tượng 33
  34. Phạm vi truy xuất Khi thiết lập quan hệ kế thừa, ta vẫn phải quan tâm đến tính đóng gói và che dấu thông tin. Điều này ảnh hưởng đến phạm vi truy xuất của các thành phần của lớp. Hai vấn đề được đặt ra là: . Truy xuất theo chiều dọc . Truy xuất theo chiều ngang 14/09/2014 Lập trình hướng đối tượng 34
  35. Phạm vi truy xuất Truy xuất theo chiều dọc: . Hàm thành phần của lớp con có quyền truy xuất các thành phần của lớp cha hay không? Truy xuất theo chiều ngang: . Các thành phần của lớp cha, sau khi kế thừa xuống lớp con, thì thế giới bên ngoài có quyền truy xuất thông qua đối tượng của lớp con hay không? 14/09/2014 Lập trình hướng đối tượng 35
  36. Truy xuất theo chiều dọc Lớp con có quyền truy xuất các thành phần của lớp cha hay không, hoàn toàn do lớp cha quyết định. Điều đó được xác định bằng thuộc tính kế thừa. Trong trường hợp lớp Sinh viên kế thừa lớp Người, Sinh viên có quyền truy xuất họ tên của chính mình (được khai báo ở lớp Người) hay không? 14/09/2014 Lập trình hướng đối tượng 36
  37. Phạm vi truy xuất class A{ void A::f() private: { int a; a = 1; b = 2; c = 3; void f(); } protected: void A::g() int b; { void g(); a = 4; b = 5; c = 6; public: } int c; void A::h(){ void h(); a = 7; b = 8; c = 9; }; } 14/09/2014 Lập trình hướng đối tượng 37
  38. Phạm vi truy xuất  Ví dụ: Cho biết trong đoạn chương trình sau câu lệnh nào đúng, câu lệnh nào sai. void main() x.b = 20; { x.g(); A x; x.c = 30; x.a = 10; x.h(); x.f(); } 14/09/2014 Lập trình hướng đối tượng 38
  39. Phạm vi truy xuất Thuộc tính public: . Thành phần nào có thuộc tính public thì có thể truy xuất từ bất cứ nơi nào. Thuộc tính private: Thành phần có thuộc tính private . Là riêng tư của lớp đó . Chỉ có hàm thành phần của lớp và ngoại lệ các hàm bạn được phép truy xuất. . Các lớp con cũng không có quyền truy xuất 14/09/2014 Lập trình hướng đối tượng 39
  40. Phạm vi truy xuất Thuộc tính protected: . Cho phép qui định một vài thành phần nào đó của lớp là bảo mật, theo nghĩa thế giới bên ngoài không được phép truy xuất, nhưng tất cả các lớp con, cháu đều được phép truy xuất. 14/09/2014 Lập trình hướng đối tượng 40
  41. Ví dụ Thuộc tính private class Nguoi { char *HoTen; int NamSinh; public: // }; class SinhVien : public Nguoi { char *MaSo; public: // void Xuat() const; }; 14/09/2014 Lập trình hướng đối tượng 41
  42. Thuộc tính private Trong ví dụ trên, không có hàm thành phần nào của lớp SinhVien có thể truy xuất các thành phần HoTen, NamSinh của lớp Nguoi. Ví dụ, đoạn chương trình sau đây sẽ gây ra lỗi: void SinhVien::Xuat() const { cout << "Sinh vien, ma so: "<<MaSo<<",ho ten:"<<HoTen; } 14/09/2014 Lập trình hướng đối tượng 42
  43. Thuộc tính private Ta có thể khắc phục lỗi trên nhờ khai báo lớp SinhVien là bạn của lớp Nguoi như trong ví dụ ban đầu: class Nguoi { friend class SinhVien; char *HoTen; int NamSinh; public: // }; 14/09/2014 Lập trình hướng đối tượng 43
  44. Thuộc tính private Khai báo lớp bạn như trên, lớp SinhVien có thể truy xuất các thành phần private của lớp Nguoi. Cách làm trên chỉ giải quyết được nhu cầu của người sử dụng khi muốn tạo lớp con có quyền truy xuất các thành phần dữ liệu private của lớp cha. Tuy nhiên, cần phải sửa lại lớp cha và tất cả các lớp ở cấp cao hơn mỗi khi có một lớp con mới. 14/09/2014 Lập trình hướng đối tượng 44
  45. Thuộc tính private class Nguoi { friend class SinhVien; friend class NuSinh; char *HoTen; int NamSinh; public: // void An() const { cout << HoTen << " an 3 chen com";} }; class SinhVien : public Nguoi { friend class NuSinh; char *MaSo; public: // }; 14/09/2014 Lập trình hướng đối tượng 45
  46. Thuộc tính protected Trong ví dụ trước, khi cài đặt lớp NuSinh ta phải thay đổi lớp cha SinhVien và cả lớp cơ sở Nguoi ở mức cao hơn. class Nguoi { protected: char *HoTen; int NamSinh; public: // }; 14/09/2014 Lập trình hướng đối tượng 46
  47. Thuộc tính protected class SinhVien : public Nguoi { protected: char *MaSo; public: SinhVien(char *ht, char *ms, int ns) : Nguoi(ht,ns){ MaSo = strdup(ms); } ~SinhVien(){ delete [ ] MaSo; } void Xuat() const; }; 14/09/2014 Lập trình hướng đối tượng 47
  48. Thuộc tính protected class NuSinh : public SinhVien { public: NuSinh(char *ht, char *ms, int ns) : SinhVien(ht,ms,ns){ } void An() const { cout << HoTen << " ma so " << MaSo << " an 2 to pho"; } }; // Co the truy xuat Nguoi::HoTen va // Nguoi::NamSinh va SinhVien::MaSo 14/09/2014 Lập trình hướng đối tượng 48
  49. Thuộc tính protected void Nguoi::Xuat() const { cout << "Nguoi, ho ten: " << HoTen << " sinh " << NamSinh; } void SinhVien::Xuat() const { cout << "Sinh vien, ma so: " << MaSo << ", ho ten: " << HoTen; // Ok: co quyen truy xuat, Nguoi::HoTen, Nguoi::NamSinh } void SinhVien::Xuat() const { cout << "Sinh vien, ma so: " << MaSo cout << ", ho ten: " << HoTen; } 14/09/2014 Lập trình hướng đối tượng 49
  50. Thuộc tính protected Là cách để tránh phải sửa đổi lớp cơ sở khi có lớp con mới hình thành Đảm bảo tính đóng gói. Thông thường ta dùng thuộc tính protected cho thành phần dữ liệu và public cho thành phần phương thức. Tóm tại, thành phần có thuộc tính protected chỉ cho phép những lớp con kế thừa được phép sử dụng. 14/09/2014 Lập trình hướng đối tượng 50
  51. Truy xuất theo chiều ngang Thành phần protected và public của lớp khi đã kế thừa xuống lớp con thì thế giới bên ngoài có quyền truy xuất thông qua đối tượng thuộc lớp con hay không? . Điều này hoàn toàn do lớp con quyết định bằng phạm vi kế thừa: Kế thừa public, Kế thừa protected, Kế thừa private 14/09/2014 Lập trình hướng đối tượng 51
  52. Phạm vi truy xuất trong kế thừa private protected public D1: public B D2: private B D3: protected B private private private protected protected protected public public public 14/09/2014 Lập trình hướng đối tượng 52
  53. Phạm vi truy xuất trong kế thừa Type of Inheritance Access private Protected public Control for for Control private ? ? ? Members protected ? ? ? public ? ? ? 14/09/2014 Lập trình hướng đối tượng 53
  54. Phạm vi truy xuất trong kế thừa Base class Type of inheritance member access public protected private specifier inheritance inheritance inheritance public in derived class. protected in derived class. private in derived class. Can be accessed directly by any Can be accessed directly by all Can be accessed directly by all Public non-static member functions, non-static member functions non-static member functions friend functions and non- and friend functions. and friend functions. member functions. protected in derived class. protected in derived class. private in derived class. Can be accessed directly by all Can be accessed directly by all Can be accessed directly by all Protected non-static member functions non-static member functions non-static member functions and friend functions. and friend functions. and friend functions. Hidden in derived class. Hidden in derived class. Hidden in derived class. Can be accessed by non-static Can be accessed by non-static Can be accessed by non-static member functions and friend member functions and friend member functions and friend Private functions through public or functions through public or functions through public or protected member functions protected member functions protected member functions of the base class. of the base class. of the base class. 14/09/2014 Lập trình hướng đối tượng 54
  55. Ví dụ 1 class daughter : public mother{ mother private: double a; public: daughter son void foo ( ); }; class mother{ protected: void daughter :: foo ( ){ int x, y; x = y = 20; public: set(5, 10); void set(int a, int b); cout<<“value of a ”<<a<<endl; private: z = 100; int z; } }; daughter can access 3 of the 4 inherited members 14/09/2014 Lập trình hướng đối tượng 55
  56. Ví dụ 2 class son : private mother{ mother private: double b; public: daughter son void foo ( ); }; class mother{ protected: void son :: foo ( ){ int x, y; x = y = 20; public: set(5, 10); void set(int a, int b); cout<<“value of b ”<<b<<endl; private: z = 100; int z; } }; 14/09/2014 Lập trình hướng đối tượng 56
  57. Phương thức thiết lập Phương thức thiết lập của lớp cơ sở luôn luôn được gọi mỗi khi có một đối tượng của lớp dẫn xuất được tạo ra. Nếu mọi phương thức thiết lập của lớp cơ sở đều đòi hỏi phải cung cấp tham số thì lớp con bắt buộc phải có phương thức thiết lập để cung cấp các tham số đó 14/09/2014 Lập trình hướng đối tượng 57
  58. Phương thức thiết lập Ví dụ 1: class A { class B : public A { public: public: A ( ) B (int a){ { cout<< “A:default”<<endl; } cout<<“B”<<endl; A (int a){ cout<<“A:parameter”<<endl; } } }; }; output: A:default B test(1); B 14/09/2014 Lập trình hướng đối tượng 58
  59. Phương thức thiết lập Ví dụ 2: class A { class C : public A public: { A ( ) public: { cout<< “A:default”<<endl; } C (int a) : A(a){ A (int a){ cout<<“C”<<endl; cout<<“A:parameter”<<endl; } } }; }; output: A:parameter C test(1); C 14/09/2014 Lập trình hướng đối tượng 59
  60. Định nghĩa các thành phần riêng Ngoài các thành phần được kế thừa, lớp dẫn xuất có thể định nghĩa thêm các thành phần riêng class HinhTron : Diem { double r; public: HinhTron( double tx, double ty, double rr) : Diem(tx, ty){ r = rr; } void Ve(int color) const; void TinhTien( double dx, double dy) const; }; HinhTron t(200,200,50); 14/09/2014 Lập trình hướng đối tượng 60
  61. Định nghĩa các thành phần riêng Lớp dẫn xuất cũng có thể override các phương thức đã được định nghĩa ở trong lớp cha. class A { class B : public A protected: { int x, y; public: public: void print (){ void print (){ cout<<“From A”<<endl; cout<<“From B”<<endl; } } }; }; 14/09/2014 Lập trình hướng đối tượng 61
  62. Truy cập phương thức class Point{ class Circle : public Point{ protected: private: double r; int x, y; public: public: void set (int a, int b, double c) { void set(int a, int b) Point ::set(a, b); //same name function call { x=a; y=b; } r = c; void foo (); } void print(); void print() { // } }; }; Circle C; Point A; C.set(10,10,100); ??? A.set(30,50); ??? C.foo (); ??? A.print(); C.print(); ??? 14/09/2014 Lập trình hướng đối tượng 62
  63. Phương thức hủy bỏ Khi một đối tượng bị hủy đi, phương thức hủy bỏ của nó sẽ được gọi. Sau đó, các phương thức hủy bỏ của lớp cơ sở sẽ được gọi một cách tự động. Vì vậy, lớp con không cần và cũng không được thực hiện các thao tác dọn dẹp cho các thành phần thuộc lớp cha. 14/09/2014 Lập trình hướng đối tượng 63
  64. Phương thức hủy bỏ - Ví dụ class SinhVien : public Nguoi { char *MaSo; public: SinhVien( char *ht, char *ms, int ns) : Nguoi(ht,ns){ MaSo = strdup(ms); } SinhVien(const SinhVien &s) : Nguoi(s){ MaSo = strdup(s.MaSo); } ~SinhVien() {delete [ ] MaSo;} // }; 14/09/2014 Lập trình hướng đối tượng 64
  65. Con trỏ và kế thừa Con trỏ trong kế thừa hoạt động theo nguyên tắc sau: . Con trỏ trỏ đến đối tượng thuộc lớp cơ sở thì có thể trỏ đến các đối tượng thuộc lớp con. . Nhưng con trỏ trỏ đến đối tượng thuộc lớp con thì không thể trỏ đến các đối tượng thuộc lớp cơ sở. . Có thể ép kiểu để con trỏ trỏ đến đối tượng thuộc lớp con có thể trỏ đến đối tượng thuộc lớp cơ sở. Tuy nhiên thao tác này có thể nguy hiểm. 14/09/2014 Lập trình hướng đối tượng 65
  66. Đa kế thừa Đa kế thừa cho phép một lớp có thể là dẫn xuất của nhiều lớp cơ sở. class A : public B, public C { }; Các đặc điểm của kế thừa đơn vẫn đúng cho trường hợp đa kế thừa. 14/09/2014 Lập trình hướng đối tượng 66
  67. Đa kế thừa Làm thế nào biểu thị tính độc lập của các thành phần cùng tên bên trong một lớp dẫn xuất? Các phương thức thiết lập và hủy bỏ được gọi như thế nào: thứ tự, truyền thông tin, ? Làm thế nào giải quyết tình trạng thừa kế xung đột trong đó, lớp D dẫn xuất từ B và C, và cả hai cùng là dẫn xuất của A 14/09/2014 Lập trình hướng đối tượng 67
  68. Đa kế thừa – Ví dụ class BASE_A{ class BASE_B public: { int a; public: int f( ){ int a; return 0; int f( ){ } return 0; int g( ){ } return 0; int g( ){ } return 0; int h( ) { return 0;} } }; }; 14/09/2014 Lập trình hướng đối tượng 68
  69. Đa kế thừa – Ví dụ class ClassC : public BASE_A, public BASE_B{ // }; void main(){ ClassC C; C.f = g; //Lỗi mơ hồ C.a = 1; //Lỗi mơ hồ C.g(); //Lỗi mơ hồ C.h(); } 14/09/2014 Lập trình hướng đối tượng 69