Sựlinhhoạtcủaphươngthứcảotrongpháttriểnnângcấpchươngtrình Ví dụ về các lớp TS và TS2 trong § 2 đã chỉ ra sự hạn chế củaphươngthức tĩnh trong việc sử dụng tính thừa kế để nâng cấp, pháttriểnchương trình. Trong § 2 cũng đã chỉ ra lớp TS2 chưa đáp ứng được yêu cầu nêu ra là in địa chỉ của thí sinh. Giải pháp cho vấn đề này rất đơn giản: Thay các phươngthức tĩnh in() bằng cách dùng chúng như các phươngthức ảo. Chươngtrình khi đó sẽ như sau: //CT6-03B // Sựlinhhoạtcủaphươngthứcảo // Lop TS TS2 #include <conio.h> #include <stdio.h> #include <iostream.h> #include <ctype.h> class TS { private: 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; } virtual void in() { fprintf(stdprn,"\n\nHo ten: %s", ht); fprintf(stdprn,"\nSo bao danh: %d", sobd); fprintf(stdprn,"\nTong diem: %0.1f", td); } void xem_in() { int ch; 339 340 cout << "\nHo ten: " << ht ; cout << "\nCo in khong? - C/K" ; ch = toupper(getch()); if (ch=='C') this->in(); // Vì in() là phươngthứcảo nên //có thể gọi đến TS::in() hoặc TS2::in() } } ; 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(); fprintf(stdprn,"\nDia chi: %s", 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ươngtrình này, chúng ta nhận thấy: Dữ liệu thí sinh in ra đã 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): 341 342 t[i].xem_in() ; Câu lệnh này gọi tới phươngthức xem_in của lớp TS2 (vì t[i] là đối tượngcủa lớp TS2). Nhưng lớp TS2 không định nghĩa phươngthức xem_in, nên phươngthức TS::xem_in() sẽ được gọi tới. Hãy theo rõi phươngthức này: void xem_in() { int ch; cout << "\nHo ten: " << ht ; cout << "\nCo in khong? - C/K" ; ch = toupper(getch()); this->in(); // Vì in() là phươngthứcảo nên //có thể gọi đến TS::in() hoặc TS2::in() } Các lệnh đầu củaphươngthứ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. Địa chỉ của t[i] (là đối tượngcủa lớp TS2) được truyền cho con trỏ this (của lớp cơ sở TS). Vì in() là phươngthứcảovà vì this đang trỏ tới đối tượng t[i] của lớp TS2, nên câu lệnh này gọi tới phươngthức TS2::in(). Trongphươngthức TS2::in() có in địa chỉ của thí sinh. Như vậy việc sử dụng các phươngthức tĩnh in() (trong các lớp TS và TS2) đã không đáp ứng được yêu cầu pháttriểnchương trình. Có một giải pháp rất đơn giản là: Định nghĩa các phươngthức in() trong các lớp TS và TS2 như các phươngthứcảo (virtual). . Sự linh hoạt của phương thức ảo trong phát triển nâng cấp chương trình Ví dụ về các lớp TS và TS2 trong § 2 đã chỉ ra sự hạn chế của phương thức tĩnh trong. Thay các phương thức tĩnh in() bằng cách dùng chúng như các phương thức ảo. Chương trình khi đó sẽ như sau: //CT6-03B // Sự linh hoạt của phương thức ảo //