Chương 5C++ và lập trình hướng đối tượngTrong chương này trình bầy các ppt

87 143 0
Chương 5C++ và lập trình hướng đối tượngTrong chương này trình bầy các ppt

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

chơng 5 Dẫn xuất thừa kế Có 2 khái niệm rất quan trọng đã làm nên toàn bộ thế mạnh của phơng pháp lập trình hớng đối tợng đó là tính kế thừa (inheritance) tính tơng ứng bội (polymorphism). Tính kế thừa cho phép các lớp đợc xây dựng trên các lớp đã có. Trong chơng này sẽ nói về sự thừa kế của các lớp. Đ 1. Sự dẫn xuất tính thừa kế 1.1. Lớp cơ sở lớp dẫn xuất Một lớp đợc xây dựng thừa kế một lớp khác gọi là lớp dẫn xuất. Lớp dùng để xây dựng lớp dẫn xuất gọi là lớp cơ sở. Lớp nào cũng có thể là một lớp cơ sở. Hơn thế nữa, một lớp có thể là cơ sở cho nhiều lớp dẫn xuất khác nhau. Đến lợt mình, lớp dẫn xuất lại có thể dùng làm cơ sở để xây dựng các lớp dân xuất khác. Ngoài ra một lớp có thể dẫn xuất từ nhiều lớp cơ sở. Dới đây là một số sơ đồ về quan hệ dẫn xuất của các lớp: Sơ đồ 1: Lớp B dẫn xuất từ lớp A, lớp C dẫn xuất từ lớp B A B C 237 238 Sơ đồ 2: Lớp A là cơ sở của các lớp B, C D A B C D Sơ đồ 3: Lớp D dẫn xuất từ 3 lớp A, B, C A B C D Sơ đồ 4: Lợc đồ dẫn xuất tổng quát A B C D E F G H Tính thừa kế: Một lớp dẫn xuất ngoài các thành phần của riêng nó, nó còn đợc thừa kế tất cả các thành phần của các lớp cơ sở có liên quan. Ví dụ trong sơ đồ 1 thì lớp C đợc thừa kế các thành phần của các lớp B A. Trong sơ đồ 3 thì lớp D đợc thừa kế các thành phần của các lớp A, B C. Trong sơ đồ 4 thì lớp G đợc thừa kế các thành phần của các lớp D, E, A, B C. 1.2. Cách xây dựng lớp dân xuất Giả sử đã định nghĩa các lớp A B. Để xây dựng lớp C dân xuất từ A B, ta viết nh sau: class C : public A, public B { private: // Khai báo các thuộc tính public: // Các phơng thức } ; 1.3. Thừa kế private public Trong ví dụ trên, lớp C thừa kế public các lớp A B. Nếu thay từ khoá public bằng private, thì sự thừa kế là private. Chú ý: Nếu bỏ qua không dùng từ khoá thì hiểu là private, ví dụ nếu định nghĩa: class C : public A, B { private: // Khai báo các thuộc tính public: // Các phơng thức } ; thì A là lớp cơ sở public của C , còn B là lớp cơ sở private của C. Theo kiểu thừa kế public thì tất cả các thành phần public của lớp cơ sở cũng là các thành phần public của lớp dẫn xuất. Theo kiểu thừa kế private thì tất cả các thành phần public của lớp cơ sở sẽ trơ thành các thành phần private của lớp dẫn xuất. 1.4. Thừa kế các thành phần dữ liệu (thuộc tính) Các thuộc tính của lớp cơ sở đợc thừa kế trong lớp dẫn xuất. Nh vậy tập thuộc tính của lớp dẫn xuất sẽ gồm: các thuộc tính mới khai báo trong định nghĩa lớp dẫn xuất các thuộc tính của lớp cơ sở. Tuy vậy trong lớp dẫn xuất không cho phép truy nhập đến các thuộc tính private của lớp cơ sở. Chú ý: Cho phép đặt trùng tên thuộc tính trong các lớp cơ sở lớp dẫn xuất. Ví dụ: class A { private: int a, b, c; public: }; class B { private: double a, b, x; public: }; class C : public A, B { private: char *a , *x ; int b ; public: }; Khi đó lớp C sẽ có các thuộc tính: 239 240 A::a , A::b, A::c (kiểu int) - thừa kế từ A B::a , B::b, B::x (kiểu double) - thừa kế từ B a, x (kiểu char*) b (kiểu int) - khai báo trong C Trong các phơng thức của C chỉ cho phép truy nhập trực tiếp tới các thuộc tính khai báo trong C. 1.5. Thừa kế phơng thức Trừ: + Hàm tạo + Hàm huỷ + Toán tử gán các phơng thức (public) khác của lớp cơ sở đợc thừa kế trong lớp dẫn xuất. Ví dụ: Trong chơng trình dới đây: + Đầu tiên định nghĩa lớp DIEM có: Các thuộc tính x, y Hai hàm tạo Phơng thức in() + Sau đó xây dựng lớp HINH_TRON dẫn xuất từ lớp DIEM, đa thêm: Thuộc tính r Hai hàm tạo Phơng thức getR Chú ý cách dùng hàm tạo của lớp cơ sở (lớp DIEM) để xây dựng hàm tạo của lớp dẫn xuất. + Trong hàm main: Khai báo đối tợng h kiểu HINH_TRON Sử dụng phơng thức in() đối với h (sự thừa kế) Sử dụng phơng thức getR đối với h //CT5-01 // Lop co so #include <conio.h> #include <iostream.h> class DIEM { private: double x, y; public: DIEM() { x = y =0.0; } DIEM(double x1, double y1) { x = x1; y = y1; } void in() { cout << "\nx= " << x << " y= " << y; } }; class HINH_TRON : public DIEM { private: double r; public: 241 242 HINH_TRON() { r = 0.0; } HINH_TRON(double x1, double y1, double r1): DIEM(x1,y1) { r = r1; } double getR() { return r; } }; void main() { HINH_TRON h(2.5,3.5,8); clrscr(); cout << "\nHinh tron co tam: "; h.in(); cout << "\nCo ban kinh= " << h.getR(); getch(); } 1.6. Líp c¬ së vµ ®èi tîng thµnh phÇn Lớp cơ sở thờng đợc xử lý giống nh một thành phần kiểu đối tợng của lớp dẫn xuất. Ví dụ chơng trình trong 1.5 có thể thay bằng một chơng trình khác trong đó thay việc dùng lớp cơ sở DIEM bằng một thành phần kiểu DIEM trong lớp HINH_TRON. Chơng trình mới có thể viết nh sau: //CT5-02 // Lop co doi tuong thanh phan #include <conio.h> #include <iostream.h> class DIEM { private: double x, y; public: DIEM() { x = y =0.0; } DIEM (double x1, double y1) { x = x1; y = y1; } void in() { cout << "\nx= " << x << " y= " << y; } } ; class HINH_TRON 243 244 { private: DIEM d; double r; public: HINH_TRON() : d() { r = 0.0; } HINH_TRON(double x1, double y1, double r1): d(x1,y1) { r = r1; } void in() { d.in(); } double getR() { return r; } }; void main() { HINH_TRON h(2.5,3.5,8); clrscr(); cout << "\nHinh tron co tam: "; h.in(); cout << "\nCo ban kinh= " << h.getR(); getch(); } Đ 2. Hàm tạo, hàm huỷ đối với tính thừa kế 2.1. Lớp dẫn xuất không thừa kế các hàm tạo, hàm huỷ, toán tử gán của các lớp cơ sở 2.2. Cách xây dựng hàm tạo của lớp dẫn xuất + Hàm tạo cần có các đối để khởi gán cho các thuộc tính (thành phần dữ liệu) của lớp. + Có thể phân thuộc tính làm 3 loại ứng với 3 cách khởi gán khác nhau: 1. Các thuộc tính mới khai báo trong lớp dẫn xuất. Trong các phơng thức của lớp dẫn xuất có thể truy xuất đến các thuộc tính này. Vì vậy chúng thờng đợc khởi gán bằng các câu lệnh gán viết trong thân hàm tạo. 2. Các thành phần kiểu đối tợng. Trong lớp dẫn xuất không cho phép truy nhập đến các thuộc tính của các đối tợng này. Vì vậy để khởi gán cho các đối tợng thành phần cần dùng hàm tạo của lớp tơng ứng. Điều này đã trình bầy trong mục Đ 8 chơng 4. 3. Các thuộc tính thừa kế từ các lớp cở sở. Trong lớp dẫn xuất không đợc phép truy nhập đến các thuộc tính này. Vì vậy để khởi gán cho các thuộc tính nói trên, cần sử dụng hàm tạo của lớp cơ sở. Cách thức cũng giống nh khởi gán cho các đối tợng thành phần, chỉ khác nhau ở chỗ: Để khởi gán cho các đối tợng thành phần ta dùng tên đối tợng thành phần, còn để khởi gán cho các thuộc tính thừa kế từ các lớp cơ sở ta dùng tên lớp cơ sở: Tên_đối_tợng_thành_phần(danh sách giá trị) Tên_lớp_cơ_sở(danh sách giá trị) Danh sách giá trị lấy từ các đối của hàm tạo của lớp dẫn xuất đang xây dựng (xem ví dụ mục 2.4 Đ 6, ví dụ 1) 2.3. Hàm huỷ 245 246 [...]... đẳng cấp quan hệ với lớp dẫn xuất Gặp trường hợp này Chương trình dịch C++ không thể quyết định được thành phần này thừa kế từ lớp nào buộc phải đưa ra một thông báo lỗi (xem ví dụ dưới đây) Cách khắc phục: Trường hợp này phải sử dụng thêm tên lớp như trình bầy trong cách 1 Ví dụ xét lớp dẫn xuất D Lớp D có 2 cơ sở là các lớp A B Giả sử các lớp A, B D được định nghĩa: 257 258 class A { private:... một đối tượng của lớp dẫn xuất được giải phóng (bị huỷ), thì các đối tượng thành phần các đối tượng thừa kế từ các lớp cơ sở cũng bị giải phóng theo Do đó các hàm huỷ tương ứng sẽ được gọi đến Như vậy khi xây dựng hàm huỷ của lớp dẫn xuất, chúng ta chỉ cần quan tâm đến các thuộc tính (không phải là đối tượng) khai báo thêm trong lớp dẫn xuất mà thôi Ta không cần để ý đến các đối tượng thành phần và. .. vi truy nhập cho các lớp dẫn xuất trực tiếp từ lớp này 3.2 Hai kiểu dẫn xuất Có 2 kiểu dẫn xuất là private public, chúng cho các phạm vi truy nhập khác nhau tới lớp cơ sở Cụ thể như sau: + Các thành phần public protected của lớp cơ sở sẽ trở thành các thành phần public protected của lớp dẫn xuất theo kiểu public + Các thành phần public protected của lớp cơ sở sẽ trở thành các thành phần private... xuất từ D E Lớp H dẫn xuất từ E 4.2 Sự thừa kế nhiều mức + Như đã biết: Lớp dẫn xuất thừa kế tất cả các thành phần (thuộc tính phương thức) của lớp cở sở, kể cả các thành phần mà lớp cơ sở được thừa kế + Hãy áp dụng nguyên lý trên để xét lớp G: - Lớp G thừa kế các thành phần của các lớp D E - Lớp D thừa kế các thành phần của lớp A B - Lớp E thừa kế các thành phần của lớp C Như vậy các thành... + Các thành phần private của lớp cở sở không cho phép truy nhập trong lớp dẫn xuất + Các thành phần public của lớp cơ sở có thể truy nhập bất kỳ chỗ nào trong chương trình Như vậy trong các lớp dẫn xuất có thể truy nhập được tới các thành phần này + Các thành phần khai báo là protected có phạm vi truy nhập rộng hơn so với các thành phần private, nhưng 251 252 hẹp hơn so với các thành phần public Các. .. nào từ B C Như vậy bây giờ D sẽ chỉ có một lớp cơ sở A duy nhất, do đó phép gán: h.a = 1 ; sẽ gán 1 cho thuộc tính a của lớp cơ sở A duy nhất mà D kế thừa Đ 6 Một số ví dụ về hàm tạo, hàm huỷ trong thừa kế nhiều mức Ví dụ 1 Ví dụ này minh hoạ cách xây dựng hàm tạo trong các lớp dẫn xuất Ngoài ra còn minh hoạ cách dùng các phương thức của các lớp cơ sở trong lớp dẫn xuất cách xử lý các đối tượng... Xuất các thuộc tính mà D thừa kế từ B } 2 Làm việc với các đối tượng của lớp dẫn xuất D h ; // Khai báo h là đối tượng của lớp D h.nhap() ; // tương tương với h.D::nhap(); h.A::xuat(); // In giá trị các thuộc tính h.A::n h.A::a h.B::xuat(); // In giá trị các thuộc tính h.B::m, h.B::n h.B::a h.D::xuat() ; // In giá trị tất cả các thuộc tính của h h.xuat() ; // tương đương với h.D::xuat() ; Đ 5 Các. .. trong lớp G gồm: - Các thành phần khai báo trong G (của riêng G) - Các thành phần khai báo trong các lớp D, E, A, B, C (được thừa kế) 4.3 Sự trùng tên Như đã nói trong 4.2: Trong lớp G có thể sử dụng (trực tiép hay gián tiếp) các thành phần của riêng G các thành phần mà nó được thừa kế từ các lớp D, E, A, B, C Yêu cầu về cách đặt tên ở đây là: + Tên các lớp không được trùng lặp + Tên các thành phần... phần các thuộc tính thừa kế từ các lớp cơ sở (xem ví dụ mục 2.4 Đ6, ví dụ 2) 2.4 Ví dụ xét các lớp + Lớp NGUOI gồm: - Các thuộc tính char *ht ; // Họ tên int ns ; - Hai hàm tạo, phương thức in() hàm huỷ + Lớp MON_HOC gồm: - Các thuộc tính char *monhoc ; // Tên môn học int st ; // Số tiết - Hai hàm tạo, phương thức in() hàm huỷ + Lớp GIAO_VIEN : - Kế thừa từ lớp NGUOI - Đưa thêm các thuộc... va C: " ; h.C::xuat(); cout . tính của các đối tợng này. Vì vậy để khởi gán cho các đối tợng thành phần cần dùng hàm tạo của lớp tơng ứng. Điều này đã trình bầy trong mục Đ 8 chơng 4. 3. Các thuộc tính thừa kế từ các lớp. và C. Trong sơ đồ 4 thì lớp G đợc thừa kế các thành phần của các lớp D, E, A, B và C. 1.2. Cách xây dựng lớp dân xuất Giả sử đã định nghĩa các lớp A và B. Để xây dựng lớp C dân xuất từ A và. tất cả các thành phần của các lớp cơ sở có liên quan. Ví dụ trong sơ đồ 1 thì lớp C đợc thừa kế các thành phần của các lớp B và A. Trong sơ đồ 3 thì lớp D đợc thừa kế các thành phần của các lớp

Ngày đăng: 18/06/2014, 11:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan