Chương 2 Lớp , Đ ối tượng và tính đóng gói 23 23 Mỗi đối tượng của một lớp có bản sao riêng của các biến được khai báo trong lớp. Bài tập I 1. Hãy tạo lớp card để giữ các mục nhập catalog thẻ thư viện, chưá tựa đề sách (kiểu chuỗi), tên tác giả (kiểu chuỗi) và số bản (kiểu nguyên). Dùng hàm thành viên chung store() để lưu trữ thông tin về sách vàhàm thành viên chung show() để hiển thò thông tin. Viết chương trình thực hiện yêu cầu trên. 2. Tạo lớp hàng đợi (queue) để giữ hàng các số nguyên. Tạo một kích thước hàng dài 100 số nguyên. Viết chương trình thực hiện yêu cầu trên. II/ Hàmtạo & hàmhủy 1/ Khái niệm Hàmtạo (constructor) có cùng tên với lớp, là hàm thành phần của một lớp, không có kiểu trả về. Mục đích của hàmtạo nhằm tạo ra các khởi đầu cho một đối tượng. Hàmtạo được gọi tự động mỗi khi đối tượng của lớp đó được tạo ra. 2/ Khai báo class class_name { // khai báo các biến vàhàm ; public : // khai báo các biến vàhàm ; class_name() ; // khai báo hàmtạo } objects_list ; Ví dụ 2.1 Lớp myclass có hàmtạo myclass() vàhàm show() #include <iostream.h> Chương 2 Lớp , Đ ối tượng và tính đóng gói 24 24 class myclass { int a; public: myclass() ; // constructor void show(); }; myclass:: myclass() // đònh nghiã hàmtạo { cout << "In constructor\n"; a = 10; } void myclass::show() { cout << a; } int main() { myclass ob; // hàmtạo myclass() được gọi tự động khi đối tượng ob được tạo ra ob.show(); return 0; } Đối với các đối tượng chung , một hàm tạo của đối tượng được gọi một lần khi chương trình bắt đầu thi hành lần đầu. Đối với các đối tượng riêng , hàm tạo của đối tượng được gọi mỗi khi lệnh khai báo được thi hành. 3/ Khái niệm hàmhủy (destructor) Hàmhủy có cùng tên với lớp, có kèm theo dấu ~ đứng trước, là hàm thành phần của một lớp, không có kiểu trả về. Mục đích của hàmhủy nhằm thi hành một số tác động khi đối tượng bò hủy bỏ, chẳng hạn một đối tượng yêu cầu cấp phát bộ nhớ khi đối tượng được tạo ra và giải Chương 2 Lớp , Đ ối tượng và tính đóng gói 25 25 phóng bộ nhớ khi đối tượng bò hủy bỏ. Hàmhủy được gọi tự động mỗi khi đối tượng của lớp đó bò hủy bỏ. 4/ Khai báo class class_name { // khai báo các biến vàhàm ; public : // khai báo các biến vàhàm ; class_name(); // khai báo hàmtạo ~class_name() ; // khai báo hàmhủy } objects_list ; Ví dụ 2.2 Lớp myclass có hàmtạo myclass() vàhàmhủy ~myclass() #include <iostream.h> class myclass { int a; public: myclass(); // constructor ~myclass() ; // destructor void show(); }; myclass::myclass() { cout << "In constructor\n"; a = 10; } myclass:: ~myclass() { cout << "Destructing .\n"; } Chương 2 Lớp , Đ ối tượng và tính đóng gói 26 26 void myclass::show() { cout << a << "\n"; } int main() { myclass ob; ob.show(); return 0; } Đối với các đối tượng chung , hàmhủy của đối tượng được gọi khi chương trình kết thúc. Đối với các đối tượng riêng , hàmhủy của đối tượng được gọi khi chúng ra khỏi phạm vi. • Lưu ý : Không thể biết được đòa chỉ của hàmtạo hoặc hàm hủy. Ví dụ 2.3 Dùng hàmtạo stack() để tự động khởi đầu ngăn xếp khi đối tượng được tạo #include <iostream.h> #define SIZE 10 // Declare a stack class for characters. class stack { char stck[SIZE]; // holds the stack int tos; // index of top-of-stack public: stack(); // constructor void push(char ch); // push character on stack char pop(); // pop character from stack }; // Initialize the stack. Chửụng 2 Lụựp , ẹ oỏi tửụùng vaứ tớnh ủoựng goựi 27 27 stack::stack() { cout << "Constructing a stack\n"; tos = 0; } // Push a character. void stack::push(char ch) { if(tos==SIZE) { cout << "Stack is full\n"; return; } stck[tos] = ch; tos++; } // Pop a character. char stack::pop() { if(tos==0) { cout << "Stack is empty\n"; return 0; // return null on empty stack } tos--; return stck[tos]; } int main() { // Create two stacks that are automatically initialized. stack s1, s2; int i; s1.push('a'); s2.push('x'); s1.push('b'); Chương 2 Lớp , Đ ối tượng và tính đóng gói 28 28 s2.push('y'); s1.push('c'); s2.push('z'); for(i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n"; for(i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n"; return 0; } Ví dụ 2.4 Dùng hàmtạo strtype() vàhàmhủy ~strtype() để tự động cấp phát bộ nhớ cho chuổi *p và giải phóng bộ nhớ khi đối tượng bò hủy. #include <iostream.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #define SIZE 255 class strtype { char *p; int len; public: strtype(); // constructor ~strtype(); //destructor void set(char *ptr); void show(); }; // Initialize a string object. strtype::strtype() { p = (char *) malloc(SIZE); if(!p) { cout << "Allocation error\n"; Chửụng 2 Lụựp , ẹ oỏi tửụùng vaứ tớnh ủoựng goựi 29 29 exit(1); } *p = '\0'; len = 0; } // Free memory when destroying string object. strtype::~strtype() { cout << "Freeing p\n"; free(p); } void strtype::set(char *ptr) { if(strlen(ptr) >= SIZE) { cout << "String too big\n"; return; } strcpy(p, ptr); len = strlen(p); } void strtype::show() { cout << p << " - length: " << len; cout << "\n"; } int main() { strtype s1, s2; s1.set("This is a test."); s2.set("I like C++."); s1.show(); Chương 2 Lớp , Đ ối tượng và tính đóng gói 30 30 s2.show(); return 0; } Ví dụ 2.5 Dùng đối tượng của lớp timer để xác đònh khoảng thời gian khi một đối tượng kiểu timer được tạovà cho đến khi bò hủy. #include <iostream.h> #include <ctime.h> class timer { clock_t start; public: timer(); // constructor ~timer(); // destructor }; timer::timer() { start = clock(); } timer::~timer() { clock_t end; end = clock(); cout << "Elapsed time: " << (end-start) / CLOCKS_PER_SEC << "\n"; } int main() { timer ob; char c; Chương 2 Lớp , Đ ối tượng và tính đóng gói 31 31 // delay . cout << "Press a key followed by ENTER: "; cin >> c; return 0; } Chương trình này dùng hàm thư viện chuẩn clock() để trả về số chu kỳ đồng hồ xảy ra từ khi chương trình bắt đầu chạy. Chia giá trò này cho hằng số CLK-TCK để chuyển thành giá trò giây. (CLK-TCK đònh nghiã số tic-tắc của đồng hồ trong một giây) Bài tập II 1. Thực hiện lại lớp queue trong bài tập I/ 2. chương 2 để thay hàm khởi đầu bằng hàm tạo. 2. Tạo lớp stopwatch để so với đồng hồ bấm giờ trong việc xác đònh thời gian trôi qua, được tính bằng giây. Các yêu cầu : - Lớp stopwatch có 2 biến riêng start và end lưu số giây - Viết hàmtạo để đạt thời gian trôi qua lúc đầu về zero. - Hai hàm thành viên start() và stop() để lần lượt mở và tắt chế độ đònh giờ. - Hàm thành viên show() để hiển thò thời gian trôi qua. - Viết hàmhủy để tự động hiển thò thời gian trôi qua khi đối tượng stopwatch bò hủy. 3. Sửa lỗi trong đoạn chương trình sau : class sample { double a, b, c; public : double sample() ; } III/ Tham số của hàmtạo . & hàm hủy 1/ Khái niệm Hàm tạo (constructor) có cùng tên với lớp, là hàm thành phần của một lớp, không có kiểu trả về. Mục đích của hàm tạo nhằm tạo. : // khai báo các biến và hàm ; class_name() ; // khai báo hàm tạo } objects_list ; Ví dụ 2.1 Lớp myclass có hàm tạo myclass() và hàm show() #include <iostream.h>