Bài tập thực hành Lập trình hướng đối tượng
+ Phần này sẽ giúp các bạn hiểu rõ hơn về các thành phần của lớp như hàm thành viên(Member Functions) , biến thành viên (data members) cũng như cách khai báo và truy cập lên các thành phần đó
+ Thực hiện các bước sau:
+ Tạo một file mới.
ne base class { private: char name[25]; int roll_no; char sex; public: void getinfo(); void display(); }; class academics //second base class { private: char course_name[25]; int semester; char grade[3]; public: void getinfo(); void display(); }; class stud_scholarship: public person_data, public academics { private: float amount; public: void getinfo(); void display(); }; void person_data::getinfo() { cout << “Ten: “; cin>> name; cout<<”So: “; cin>>roll_no; cout<<”Gioi tinh(F/M) : “; cin>> sex; } void person_data:: display() { cout<<name<<”\t”; cout<<roll_no<<”\t”; cout<<sex<<”\t”; } void academics::getinfo() { cout<<”Ten khoa (BA/MBA/MCA etc)? “; cin>>course_name; cout<< “Hoc ky (1/2/3/...)? “; cin>>semester; cout<<”muc do (A,B,B+,B-..) ? ”; cin>>grade; } void academics::display() { cout<<course_name<<”\t”; cout<<semester<<”\t”; cout<<grade<<”\t”; } void stud_scholarship::getinfo() { person_data::getinfo(); academics::getinfo(); cout<<”Su ho tro “; cin>>amount; } void stud_scholarship::display() { person_data::display(); academics::display(); cout<<setprecision(2); cout<<amount<<endl;} void main() { clrscr(); stud_scholarship obj; cout<<”Nhap cac thong tin sau: “<<endl; obj.getinfo(); cout<<endl; cout<<”Ten So Gioi tinh Khoa Hoc ky Muc do”; cout<<”Amount”<<endl; obj.display(); } Lưu file với tên “multi52.cpp” Dịch và chạy chương trình Đóng file “danag411.cpp” Trong chương trình trên, các lớp cơ sở có hàm trùng tên vì vậy khi lớp dẫn xuất gọi các hàm này phải chỉ rõ là hàm dược gọi của lớp nào (xem hàm getinfo và hàm display của lớp dẫn xuất). Hàm khởi tạo trong kế thừa Khi trong lớp cơ sở và lớp dẫn xuất có hàm khởi tạo (constructors) thì lớp cơ sở sẽ được khởi tạo trước với hàm khởi tạo mặc định hoặc hàm có tham số tùy thuộc vào khai báo ở trong lớp dẫn xuất. Tạo file mới Gõ đoạn chương trình sau #include #include class Alpha { public: Alpha() { cout<< “Ham khoi tao cua lop Alpha”<<endl; } }; class Beta:public Alpha { public: Beta():Alpha() { cout<< “Ham khoi tao cua lop Beta, ke thua tu lop Alpha” <<endl; } }; class Gamma: public Alpha { public: Gamma():Alpha() { cout<< “Ham khoi tao lop Gamma, ke thua thu lop Alpha” <<endl; } }; class Delta: public Gamma, public Beta { Beta b; //base class object public: Delta():Gamma(),Beta() { cout<< “Ham khoi tao lop Delta, ke thua thu lop Beta ” << “va lop Gamma, \n” << “co mot doi tuong Beta o trong “ <<endl; } }; void main() { clrscr(); cout<<”Khai bao mot doi tuong cua lop Alpha \n”; Alpha aa; cout<<endl; cout<<”Khai bao mot doi tuong cua lop Beta \n”; Beta bb; cout<<endl; cout<<”Khai bao mot doi tuong cua lop Gamma \n”; Gamma cc; cout<<endl; cout<<”Khai bao mot doi tuong cua lop Delta \n”; Delta dd; cout<<endl; } Lưu file với tên “multi53.cpp” Dịch và chạy chương trình Màn hình kết quả như sau: Khai bao mot doi tuong cua lop Alpha Ham khoi tao cua lop Alpha Khai bao mot doi tuong cua lop Beta Ham khoi tao cua lop Alpha Ham khoi tao cua lop Beta, ke thua tu lop Alpha Khai bao mot doi tuong cua lop Gamma Ham khoi tao cua lop Alpha Ham khoi tao lop Gamma, ke thua thu lop Alpha Khai bao mot doi tuong cua lop Delta Ham khoi tao cua lop Alpha Ham khoi tao lop Gamma, ke thua thu lop Alpha Ham khoi tao cua lop Alpha Ham khoi tao cua lop Beta, ke thua tu lop Alpha Ham khoi tao cua lop Alpha Ham khoi tao cua lop Beta, ke thua tu lop Alpha Ham khoi tao lop Delta, ke thua thu lop Beta va lop Gamma, co mot doi tuong Beta o trong Đóng file “danag411.cpp” Trong chương trình trên các bạn sẽ thấy được thứ tự các hàm khởi tạo được gọi như thế nào. Bµi thùc hµnh: BÀI THỰC HÀNH SỐ 6 Môc tiªu: + Thực hành cách viết chương trình có sử dụng cơ chế đa hình(polymorphism). + Làm rõ các khái niệm: hàm ảo, hàm thuần ảo, và hàm hủy ảo (Virtual destructor). BÀI TẬP THỰC HÀNH 6.1 Cơ chế đa hình (Polymorphism). 6.2 Hàm ảo (Virtual functions). 6.3 Hàm thuần ảo. 6.4 Hàm hủy ảo(Virtual destructors). 6.1 Cơ chế đa hình (Polymorphism). Cơ chế đa hình trong C++ là cơ chế cho phép hành vi đối tượng có thể có nhiều thể hiện khác nhau tùy thuộc vào lớp thực chất mà đối tượng đó thuộc về. Khả năng cho phép một chương trình sau khi đã biên dịch có thể có nhiều diễn biến xảy ra là một trong những thể hiện của tính đa hình – tính muôn màu muôn vẻ – của chương trình hướng đối tượng, một thông điệp được gởi đi (gởi đến đối tượng) mà không cần biết đối tượng nhận thuộc lớp nào. Để thực hiện được tính đa hình, các nhà thiết kế C++ cho chúng ta dùng cơ chế kết nối động (dynamic binding) thay cho cơ chế kết nối tĩnh (static binding) ngay khi chương trình biên dịch được dùng trong các ngôn ngữ cổ điển như C, Pascal, 6.2 Hàm ảo (Virtual functions). Hàm ảo là hàm phải được mô tả trong lớp cơ bản, Trước hàm ảo phải có từ khoá virtual. Ta xét ví dụ sau: #include #include #include class person { protected: char *name; public: person(char *n) { name = n;} virtual void print() // hàm ảo { cout << “My name is :”<<name << endln; } }; class foreigner : public person { public: foreigner(char *n) : person(n) { } void printf() { cout <<ll mio nome e” <<name <<endln; } }; class alien : public person { public: alien(char *n) :person(n){ } void print() { cout <<”&*^*&%& **^@<<name<<endln; cout << sorry, there’s a communication problem”; } }; void main() { clrscr(); person* p1; person *p2; p1 = new person(“Jack”); p2 = new foreigner(“Maria”); cout <<”Introducing a Person:” <<endln; p1->print(); cout <<”Introducing a Foreigner:” <<endln; p2->print(); p1 = new foreigner(“Al Pacino”); cout << “Reintroducing the Person:” << endln; p1 ->print(); person* p3; p3 = new alien(“Martian”); cout << “Introducing a alien:” << endln; p3 ->print(); } Kết quả sau khi chạy chương trình: Introducing the Person: My name is Jack Introducing the Foreiger: ll mi o nome a Maria Reintroducing the person: ll mio nome e Al Pacino Introducing the alien: &*^*&%& **^@ Martian Sorry there’s a communication problem Trong ví dụ trên ta thấy cả hai lớp dẫn xuất đều có hàm print như trong lớp cơ bản của chúng, hàm print trong lớp person là một hàm ảo. Ban đầu cả hai con trỏ p1 và p2, p3 đếu có kiểu person nhưng sau đó p1 lại thực sự trỏ đến một đối tượng kiểu person trong khi p2 lại trỏ đến một đối tượng kiểu foreigner và p3 trỏ đến đối tượng kiểu alien. Khi thực hiện p2 không gọi hàm print của lớp person mà gọi hàm print của lớp foreigner , và p3 gọi hàm print của lớp alien. Đây chính là cơ chế đa hình mà ta đã nói ở trên. 6.3 Hàm thuần ảo. Hàm thuần ảo là hàm ảo được mô tả bằng cách gán giá trị 0 cho hàm. Một lớp được gọi là lớp trừu tượng nếu trong lớp tồn tại một hàm ảo và không thể dùng lớp này để định nghĩa một đối tượng. Xét chương trình sau: #include #include class format { public; void display_form(); virtual void header() { cout << this is a header\n”; } virtual void body() = 0; // hàm thuần ảo virtual void footer() { cout << “this is a footer\n\n”; } } void Format :: display_form() { header(); for( int index = 0;index <3 ; index ++) { body(); } footer(); } class MyForm : public Format { public: void body() { cout << “This is the new body of text\n”;} void footer(){ cout << This is the new footer\n”;} }; void main() { clrscr(); Format* first_form = new MyForm; First_form->display_form(); } 6.4 Hàm hủy ảo(Virtual destructors). Hàm hủy là hàm được gọi một cách tự động để thực hiện một số công việc nào đó mà người lập trình cần khi đối tượng bị hủy , chẳng hạn hàm hủy dùng để giải phóng bộ nhớ một cách tự động khi đối tượng bị hủy. Tuy nhiên bình thường thì hàm hủy của lớp dẫn xuất sẽ không được gọi mà chỉ có hàm hủy của lớp cơ bản được gọi , nên trong một số trường hợp ta không thể dùng hàm ảo trong một lớp dẫn xuất để thực hiện các thao tác mà ta cần khi một làm khi một đối tượng của lớp mày bị hủy. Vấn đền này được giải quyết bằng cách dúng hàm hủy ảo. Hàm hủy của lớp cơ bản sẽ là một hàm ảo, các lớp dẫn xuất sẽ có hàm hủy riêng và khi đối tượng bị hủy ,hàm hủy của lớp cơ bản và lớp dẫn xuất đều sẽ được gọi. Xét ví dụ sau; #include class Base { public: ~Base() { cout<<"~Base"<<endl; } }; class Derived:public Base { public: ~Derived() { cout<<"~Derived"<<endl; } }; int main() { Base *B; B = new Derived; delete B; return 0; } Kết quả khi thực hiện : ~Base Như vậy ta thấy chỉ có hàm hủy của lớp cơ bản được gọi , còn hàm hủy của lớp dẫn xuất không được gọi . Bây giờ ta sửa lại chương trình trên như sau: #include class Base { public: virtual ~Base() { cout<<"~Base"<<endl; } }; class Derived:public Base { public: virtual ~Derived() { cout<<"~Derived"<<endl; } }; int main() { Base *B; B = new Derived; delete B; return 0; } Khi đó kết quả của chương trình sẽ là ; ~ Base ~Derived Bµi tËp lµm thªm Xây dựng các lớp theo sơ đồ sau đây : HINH H_TRON H_CHUNHAT Trong đó HINH là lớp cơ bản, H_TRON, H_CHUNHAT là các lớp dẩn xuất, lớp hình có các hàm ảo thuần ảo virtual void Ve() // hàm vẽ hình ra màn hình virtual int TinhDienTich() // hàm tính diện tích Các lớp dẫn xuất sẽ viết lại các hàm trên để vẽ hay tính diện tích cho thích hợp.
File đính kèm:
- Bài tập thực hành Lập trình hướng đối tượng.doc