Tương ứng bộ và phương thức ảo

36 283 0
Tương ứng bộ và phương thức ảo

Đ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

191 CHƯƠNG 7 TƯƠNG ỨNG BỘI PHƯƠNG THỨC ẢO Tương ứng bội phương thức ảo là công cụ mạnh của C ++ cho phép tổ chức quản lý các ñối tượng khác nhau theo cùng một lược ñồ. Chương này sẽ trình bầy cách sử dụng các công cụ trên ñể xây dựng chương trình quản lý nhiều ñối tượng khác nhau theo một lược ñồ thống nhất. § 1. PHƯƠNG THỨC TĨNH 1.1. Lời gọi tới phương thức tĩnh Như ñã biết một lớp dẫn xuất ñược thừa kế các phương thức của các lớp cơ sở tiền bối của nó. Ví dụ lớp A là cơ sở của B, lớp B lại là cơ sở của C, thì C có 2 lớp cơ sở tiền bối là B A. Lớp C ñược thừa kế các phương thức của A B. Các phương thức mà chúng ta vẫn nói là các phương thức tĩnh. ðể tìm hiểu thêm về cách gọi tới các phương thức tĩnh, ta xét ví dụ về các lớp A, B C như sau: class A { public: void xuat() { cout << "\n Lop A " ; } }; class B: public A { public: void xuat() { cout << "\n Lop B " ; } }; class C: public B { public: 192 void xuat() { cout << "\n Lop C " ; } }; Lớp C có hai lớp cơ sở tiền bối là A B., nên lớp C kế thừa các phương thức của A B. Do ñó một ñối tượng của C sẽ có tới ba phương thức xuat. Hãy theo dõi các câu lệnh sau: C h ; // h là ñối tượng kiểu C h.B::xuat() ; // Gọi tới phương thức h.B::xuat() h.A::xuat() ; // Gọi tới phương thức h.A::xuat() Các lời gọi phương thức trong ví dụ trên ñều xuất phát từ ñối tượng h mọi lời gọi ñều xác ñịnh rõ phương thức cần gọi. Bây giờ chúng ta hãy xét các lời gọi không phải từ một biến ñối tượng mà từ một con trỏ. Xét các câu lệnh: A *p, *q, *r; // p, q, r là con trỏ kiểu A A a; // a là ñối tượng kiểu A B b; // b là ñối tượng kiểu B C c; // c là ñối tượng kiểu C Chú ý: Con trỏ của lớp cơ sở có thể dùng ñể chứa ñịa chỉ các ñối tượng của lớp dẫn xuất. Như vậy cả 3 phép gán sau ñều hợp lệ: p = &a ; q = &b ; r = &c ; Tiếp tục xét các lời gọi phương thức từ các con trỏ p, q, r: p->xuat(); q->xuat(); r->xuat(); hãy lý giải xem phương thức nào (trong các phương thức A::xuat, B::xuat C::xuat ñược gọi? Câu trả lời là: Cả ba câu lệnh trên ñều gọi tới phương thức A::xuat() , vì các con trỏ p, q r ñều có kiểu A. Như vậy có thể tóm lược cách thức gọi các phương thức tĩnh như sau: Lời gọi tới phương thức tĩnh bao giờ cũng xác ñịnh rõ phương thức nào (trong số các phương thức trùng tên của các lớp có quan hệ thừa kế) ñược gọi. 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. Nếu lời 193 gọi xuất phát từ một con trỏ kiểu lớp nào, thì phương thức của lớp ñó sẽ ñược gọi bất kể con trỏ chứa ñịa chỉ của ñối tượng nào. 1.2. Ví dụ Xét bốn lớp A, B, C D. Lớp B C có chung lớp cơ sở A. Lớp D dẫn xuất từ C. Cả bốn lớp ñều có phương thức xuat. #include <conio.h> #include <stdio.h> #include <iostream.h> #include <ctype.h> class A { int n; public: A() { n=0; } A(int n1) { n=n1; } void xuat() { cout << "\nLop A: "<< n; } int getN() { return n; } }; class B: public A { public: B():A() { } B(int n1): A(n1) { } void xuat() 194 { cout << "\nLop B: "<<getN(); } }; class C: public A { public: C():A() { } C(int n1):A(n1) { } void xuat() { cout << "\nLop C: "<<getN(); } }; class D: public C { public: D():C() { } D(int n1):C(n1) { } void xuat() { cout << "\nLop D: "<<getN(); } }; void hien(A *p) { p->xuat(); 195 } void main() { A a(1); B b(2); C c(3); D d(4); clrscr(); hien(&a); hien(&b); hien(&c); hien(&d); getch(); } Nhận xét hàm: void hien(A *p) { p->xuat(); } Không cần biết tới ñịa chỉ của ñối tượng nào sẽ truyền cho ñối con trỏ p, lời gọi trong hàm luôn luôn gọi tới phương thức A::xuat() vì con trỏ p kiểu A. Như vậy bốn câu lệnh: hien(&a); hien(&b); hien(&c); hien(&d); trong hàm main (của chương trình trên ñây) ñều gọi tới A::xuat(). § 2. SỰ HẠN CHẾ CỦA PHƯƠNG THỨC TĨNH Ví dụ sau cho thấy sự hạn chế của phương thức tĩnh trong việc sử dụng tính thừa kế ñể phát triển chương trình. Giả sử cần xây dựng chương trình quản lý thí sinh. Mỗi thí sinh ñưa vào ba thuộc tính: Họ tên, số báo danh tổng ñiểm. Chương trình gồm ba chức năng: + nhap: Nhập dữ liệu thí sinh gồm họ tên, số báo danh, tổng ñiểm + xem_in: In họ tên thí sinh ra màn hình, sau ñó lựa chọn hoặc in hoặc không + in: In ñầy ñủ dữ liệu thí sinh ra mà hình Chương trình dưới ñây sử dụng lớp TS (Thí sinh) ñáp ứng ñược yêu cầu ñặt ra. 196 #include <conio.h> #include <iostream.h> #include <ctype.h> class TS { char ht[25]; int sobd; float td; public: void nhap() { cout << "\nHo ten: " ; fflush(stdin); gets(ht); cout << "So bao danh: " ; cin >> sobd; cout << "Tong diem: " ; cin >> td; } void in() { cout<<"\nHo ten: "<<ht; cout<<"\nSo bao danh: "<<sobd; cout<<"\nTong diem: "<<td; } void xem_in() { int ch; cout << "\nHo ten: " << ht ; cout << "\nCo in khong? - C/K" ; ch = toupper(getch()); if (ch=='C') this->in(); } } ; void main() { 197 TS t[100]; int i, n; cout << "\nSo thi sinh: "; cin >> n; for (i=1; i<=n; ++i) t[i].nhap(); for (i=1; i<=n; ++i) t[i].xem_in(); getch(); } Giả sử Nhà trường muốn quản lý thêm ñịa chỉ của thí sinh. Vì sự thay ñổi ở ñây là không nhiều, nên ta xây dựng lớp mới TS2 dẫn xuất từ lớp TS. Trong lớp TS2 ñưa thêm thuộc tính dc (ñịa chỉ) các phương thức nhap, in. Cụ thể lớp TS2 ñược ñịnh nghĩa như sau: class TS2: public TS { private: char dc[30] ; // Dia chi public: void nhap() { TS::nhap(); cout << "Dia chi: " ; fflush(stdin); gets(dc); } void in() { TS::in(); cout<<"\nDia chi: "<<dc; } }; Trong lớp TS2 không xây dựng lại phương thức xem_in, mà sẽ dùng phương thức xem_in của lớp TS. Chương trình mới như sau: #include <conio.h> 198 #include <stdio.h> #include <iostream.h> #include <ctype.h> class TS { char ht[25]; int sobd; float td; public: void nhap() { cout << "\nHo ten: " ; fflush(stdin); gets(ht); cout << "So bao danh: " ; cin >> sobd; cout << "Tong diem: " ; cin >> td; } void in() { cout<<"\nHo ten: "<<ht; cout<<"\nSo bao danh: "<<sobd; cout<<"\nTong diem: "<<td; } void xem_in() { int ch; cout << "\nHo ten: " << ht ; cout << "\nCo in khong? - C/K" ; ch = toupper(getch()); if (ch=='C') this->in(); //Goi den TS::in(), vi this la con tro kieu TS } } ; class TS2: public TS 199 { private: char dc[30] ; // Dia chi public: void nhap() { TS::nhap(); cout << "Dia chi: " ; fflush(stdin); gets(dc); } void in() { TS::in(); cout<<"\nDia chi: "<<dc; } }; void main() { TS2 t[100]; int i, n; cout << "\nSo thi sinh: "; cin >> n; for (i=1; i<=n; ++i) t[i].nhap(); for (i=1; i<=n; ++i) t[i].xem_in(); getch(); } Khi thực hiện chương trình này, chúng ta nhận thấy: Dữ liệu in ra vẫn không có ñịa chỉ. ðiều này có thể giải thích như sau: Xét câu lệnh (thứ 2 từ dưới lên trong hàm main): t[i].xem_in() ; 200 Câu lệnh này gọi tới phương thức xem_in của lớp TS2 (vì t[i] là ñối tượng của lớp TS2). Nhưng lớp TS2 không ñịnh nghĩa phương thức xem_in, nên phương thức TS::xem_in() sẽ ñược gọi tới. Hãy theo dõi phương thức này: void xem_in() { int ch; cout << "\nHo ten: " << ht ; cout << "\nCo in khong? - C/K" ; ch = toupper(getch()); if(ch=='C') this->in(); //Goi den TS::in(), vi this la con tro kieu TS } Các lệnh ñầu của phương thức sẽ in họ tên thí sinh. Nếu chọn có (bấm phím C), thì câu lệnh: this->in() ; sẽ ñược thực hiện. Mặc dù ñịa chỉ của t[i] (là ñối tượng của lớp TS2) ñược truyền cho con trỏ this, thế nhưng câu lệnh này luôn luôn gọi tới phương thức TS::in(), vì con trỏ this ở ñây có kiểu TS vì in() là phương thức tĩnh. Do ñó kết quả là không in ñược ñịa chỉ của thí sinh. Như vậy việc sử dụng các phương thức tĩnh in (trong các lớp TS TS2) ñã không ñáp ứng ñược yêu cầu phát triển chương trình. ðể khắc phục ñiều này, chúng ta có thể nghĩ ñến ngay một giải pháp: xây dựng thêm phương thức xem_in cho lớp TS2. Tuy nhiên ñiều này không chỉ làm cho chương trình rườm rà hơn mà vẫn không thể ñáp ứng ñược yêu cầu, vì trong TS2 ta không thể truy nhập ñược các thành phần họ tên, số báo danh, tổng ñiểm. Trong C ++ có một giải pháp rất hiệu quả ñể xử lý vấn ñề này là: ðịnh nghĩa các phương thức in trong các lớp TS TS2 như các phương thức ảo (virtual method). § 3. PHƯƠNG THỨC ẢO TƯƠNG ỨNG BỘI 3.1. Cách ñịnh nghĩa phương thức ảo Giả sử A là một lớp cơ sở, các lớp B, C, D dẫn xuất (trực tiếp hoặc gián tiếp) từ A. Giả sử trong bốn lớp trên ñều có các phương thức trùng dòng tiêu ñề (trùng kiểu, trùng tên, trùng các ñối). ðể ñịnh nghĩa các phương thức này là các phương thức ảo, ta chỉ cần: + Hoặc thêm từ khoá virtual vào dòng tiêu ñề của phương thức bên trong ñịnh nghĩa lớp cơ sở A. [...]... § 6 S D NG TƯƠNG NG B I PHƯƠNG TH C O 6.1 Cách s d ng tương ng b i Tương ng b i cho phép xét các v n ñ khác nhau, các ñ i tư ng khác nhau, các phương pháp khác nhau, các cách gi i quy t khác nhau theo cùng m t lư c ñ chung Các bư c áp d ng tương ng b i có th t ng k t l i như sau: + Xây d ng l p cơ s tr u tư ng bao g m nh ng thu c tính chung nh t c a các th c th c n qu n lý ðưa vào các phương th c... phát t m t con tr ki u l p nào, thì phương th c c a l p ñó s ñư c g i b t k con tr ch a ñ a ch c a ñ i tư ng nào Quy t c g i phương th c o: Phương th c o khác phương th c tĩnh khi ñư c g i t m t con tr L i g i t i phương th c o t m t con tr chưa cho bi t rõ phương th c nào (trong s các phương th c o trùng tên c a các l p có quan h th a k ) s ñư c g i ði u này ph thu c vào ñ i tư ng c th mà con tr ñang... ðây là l p A” ; } 3.2 Quy t c g i phương th c o ð có s so sánh v i phương th c tĩnh, ta nh c l i quy t c g i phương th c tĩnh nêu trong §1 Quy t c g i phương th c tĩnh: L i g i t i phương th c tĩnh bao gi cũng xác ñ nh rõ phương th c nào (trong s các phương th c trùng tên c a các l p có quan h th a k ) ñư c g i 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... cho các l p có ch a các phương th c o thu n tuý Phương th c o thu n tuý là m t phương th c o mà n i dung c a nó không có gì Cách th c ñ nh nghĩa m t phương th c o thu n tuý như sau: virtual void tên _phương_ th c() = 0 ; Ví d : class A { public: virtual void nhap() = 0 ; virtual void xuat() = 0 ; void chuong(); }; Trong ví d trên, thì A là l p cơ s tr u tư ng Các phương th c nhap xuat ñư c khai báo... c cài ñ t các phương th c này) Phương th c chuong là m t phương th c bình thư ng s ph i có m t ñ nh nghĩa ñâu ñó cho phương th c này 208 Không có ñ i tư ng nào c a m t l p tr u tư ng l i có th ñư c phát sinh Tuy nhiên các con tr các bi n tham chi u ñ n các ñ i tư ng c a l p tr u tư ng thì v n h p l B t kỳ l p nào 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... p->hien_thi() luôn luôn g i t i phương th c A::hien_thi() Như v y m t l i g i (xu t phát t con tr ) t i phương th c tĩnh luôn luôn liên k t v i m t phương th c c ñ nh s liên k t này xác ñ nh trong quá trình biên d ch chương trình Cũng v i l i g i: p->hien_thi() ; như trên, nhưng n u hien_thi() là các phương th c o, thì l i g i này không liên k t c ng v i m t phương th c c th nào Phương th c mà nó liên k... tư ng, vì trong l p không có các phương th c thu n tuý o Phương th c xung_ten: virtual void xung_ten() { } 213 là phương th c o, ñư c ñ nh nghĩa ñ y ñ , m c dù thân c a nó là r ng Do v y khai báo: CON_VAT cv(“Con vat chung”); v n ñư c C++ ch p nh n Bây gi n u ñ nh nghĩa l i phương th c xung_ten như sau: virtual void xung_ten() = 0 ; thì nó tr thành phương th c thu n o C++ s quan ni m l p CON_VAT là... u là con tr a tr t i m t vùng nh ch a d y s nguyên c n s p x p - Phương th c hoan_vi(i,j) dùng ñ hoán v các ph n t a[i] a[j] Phương th c này ñư c dùng trong 3 l p d n xu t bên dư i - Phương th c o sapxep(a1,n) dùng ñ s p x p d y n s nguyên ch a trong m ng a1 + Ba l p d n xu t là: select_sort, quick_sort heap_sort M i l p ñ u có phương th c o: virtual void sapxep(int *a1, long n) ; ñ th c hi n... D::hien_thi() 3.3 Tương ng b i Chúng ta nh n th y cùng m t câu l nh: p->hien_thi(); tương ng v i nhi u phương th c khác nhau ðây chính là tương ng b i Kh năng này rõ ràng cho phép x lý nhi u ñ i tư ng khác nhau, nhi u công vi c, th m chí nhi u thu t toán khác nhau theo cùng m t cách th c, cùng m t lư c ñ ði u này s ñư c minh ho trong các m c ti p theo 3.4 Liên k t ñ ng Có th so sánh s khác nhau gi phương th... a ñ a ch a ñ a ch a ñ a ch a ñ a ch ñ ñ ñ ñ i tư i tư i tư i tư ng l ng l ng l ng l pA pB pC pD Như v y m t l i g i (xu t phát t con tr ) t i phương th c o không liên k t v i m t phương th c c ñ nh, mà tuỳ thu c vào n i dung con tr ðó là s liên k t ñ ng phương th c ñư c liên k t (ñư c g i) thay ñ i m i khi có s thay ñ i n i dung con tr trong quá trình ch y chương trình 3.5 Quy t c gán ñ a ch ñ . phương thức in trong các lớp TS và TS2 như các phương thức ảo (virtual method). § 3. PHƯƠNG THỨC ẢO VÀ TƯƠNG ỨNG BỘI 3.1. Cách ñịnh nghĩa phương thức ảo. 191 CHƯƠNG 7 TƯƠNG ỨNG BỘI VÀ PHƯƠNG THỨC ẢO Tương ứng bội và phương thức ảo là công cụ mạnh của C ++ cho phép tổ chức

Ngày đăng: 30/09/2013, 00:20

Từ khóa liên quan

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

  • Đang cập nhật ...

Tài liệu liên quan