Truyền các đối tượng sang hàm

8 300 0
Truyền các đối tượng sang hàm

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

Thông tin tài liệu

Chương 2 Lớp , Đ ối tượng và tính đóng gói 46 46 int i, j; public: cl2(int a, int b) { i = a; j = b; } // . }; int main() { cl1 x(10, 20); cl2 y(0, 0); x = y; // . } 2. Viết chương trình dựa vào lớp queue trong bài tập II/ 1. chương II chứng tỏ một hàng đợi có thể được gán cho một hàng đợi khác. 3. Nếu lớp queue trong câu 2. cấp phát bộ nhớ động để giữ hàng đợi, tại sao trong trường hợp này, một hàng đợi không thể được gán cho hàng đợi khác. VI/ Truyền các đối tượng sang hàm 1/ Việc truyền các đối tượng cho hàm giống như truyền các đối số thông thường. Tham số của hàm có kiểu dữ liệu là kiểu lớp, và đối số truyền cho hàm chính là đối tượng . Giống như các kiểu dữ liệu khác, theo ngầm đònh, tất cả các đối tượng được truyền bởi giá trò cho một hàm. Ví dụ 6.1 Truyền một đối tượng cho hàm. #include <iostream.h> class samp { int i; public: Chương 2 Lớp , Đ ối tượng và tính đóng gói 47 47 samp(int n) { i = n; } int get_i() { return i; } }; // Return square of o.i. int sqr_it( samp o ) { return o.get_i() * o.get_i(); } int main() { samp a(10), b(2); cout << sqr_it( a ) << "\n"; cout << sqr_it( b ) << "\n"; return 0; } 2/ Do đối tượng được truyền bởi giá trò cho một hàm, có nghóa là việc sao chép từng bit của đối số được thực hiện và chính sao chép này được sử dụng bởi hàm. Do đó, những thay đổi cho đối tượng bên trong hàm không có ảnh hưởng đến sự gọi đối tượng. Ví dụ 6.2 #include <iostream.h> class samp { int i; public: samp(int n) { i = n; } void set_i(int n) { i = n; } int get_i() { return i; } }; // Set o.i to its square. This has no effect on the object used to call sqr_it(), Chương 2 Lớp , Đ ối tượng và tính đóng gói 48 48 however. void sqr_it( samp o ) { o.set_i( o.get_i() * o.get_i() ) ; cout << "Copy of a has i value of " << o.get_i(); cout << "\n"; } int main() { samp a(10); sqr_it( a ) ; // a passed by value, displays 100 cout << "But, a.i is unchanged in main: "; cout << a.get_i(); // displays 10 return 0; } 3/ Khi truyền điạ chỉ của đối tượng sang hàm (sẽ không tạo ra bản sao đối tượng), nội dung của đối tượng sẽ bò thay đổi. Ví dụ 6.3 #include <iostream.h> class samp { int i; public: samp(int n) { i = n; } void set_i(int n) { i = n; } int get_i() { return i; } }; /* Set o.i to its square. This affects the calling argument. */ void sqr_it( samp *o ) { Chương 2 Lớp , Đ ối tượng và tính đóng gói 49 49 o->set_i(o->get_i() * o->get_i()); cout << "Copy of a has i value of " << o->get_i(); cout << "\n"; } int main() { samp a(10); sqr_it( &a ); // pass a's address to sqr_it(), displays 100 cout << "Now, a in main() has been changed: "; cout << a.get_i(); // displays 100 return 0; } 4/ Bản sao của đối tượng Khi truyền một đối tượng cho hàm, một bản sao của đối tượng được thực hiện, có nghóa là một đối tượng mới xuất hiện. Do đó khi hàm kết thúc làm việc, bản sao của đối tượng đó (đối số của hàm) sẽ bò hủy. Điều này làm nảy sinh hai vấn đề : - Hàm tạo của đối tượng được gọi khi bản sao thực hiện ? - Hàm hủy của đối tượng được gọi khi bản sao bò hủy ? Khi bản sao của một đối tượng được thực hiện để dùng gọi hàm, thì hàm tạo không được gọi . Do hàm tạo thường được dùng để khởi đầu một khiá cạnh nào đó của đối tượng. Khi truyền một đối tượng cho một hàm, bạn cần đến trạng thái hiện hành của đối tượng chứ không phải trạng thái ban đầu. Khi hàm kết thúc và bản sao bò hủy, hàm hủy được gọi . Ví dụ 6.4 #include <iostream.h> class samp { int i; Chương 2 Lớp , Đ ối tượng và tính đóng gói 50 50 public: samp(int n) { i = n; cout << "Constructing\n"; } ~samp() { cout << "Destructing\n"; } int get_i() { return i; } }; // Return square of o.i. int sqr_it( samp o ) { return o.get_i() * o.get_i(); } int main() { samp a(10); cout << sqr_it( a ) << "\n"; return 0; } Nội dung chương trình thực hiện Constructing Destructing 100 Destructing Giải thích ? Hàm hủy của bản sao đối tượng được gọi khi hàm kết thúc có thể là nguyên nhân của nhiều vấn đề. Chẳng hạn, nếu đối tượnghàm tạo cấp phát bộ nhớ động hoặc hàm hủy giải phóng bộ nhớ động, thì bản sao của đối tượng sẽ giải phóng bộ nhớ động khi hàm Chương 2 Lớp , Đ ối tượng và tính đóng gói 51 51 hủy của nó được gọi. Điều này làm cho đối tượng gốc bò hỏng và trở thành vô dụng. Ví dụ 6.5 // This program contains an error. #include <iostream.h> #include <stdlib.h> class dyna { int *p; public: dyna(int i); ~dyna() { free(p); cout << "freeing \n"; } int get() { return *p; } }; dyna::dyna(int i) { p = (int *) malloc(sizeof(int)); if(!p) { cout << "Allocation failure\n"; exit(1); } *p = i; } // Return negative value of *ob.p int neg( dyna ob ) { return -ob.get(); } int main() { dyna o(-10); cout << o.get() << "\n"; // -10 Chương 2 Lớp , Đ ối tượng và tính đóng gói 52 52 cout << neg( o ) << "\n"; // freeing // 10 dyna o2(20); cout << o2.get() << "\n"; // 20 cout << neg( o2 ) << "\n"; // freeing // -20 cout << o.get() << "\n"; // 20 do *p được cấp đòa chỉ vùng nhớ động cout << neg( o ) << "\n"; // freeing // -20 return 0; // freeing o // freeing o2 // Null pointer assignment } Giải thích nguyên nhân gây lổi ? • Có thể khắc phục bằng cách truyền điạ chỉ của đối tượng cho hàm. Vì sẽ không có đối tượng mới được tạo ra và không có hàm hủy của bản sao đối tượng được gọi khi hàm trả về. Tuy nhiên, giải pháp tốt nhất là sử dụng hàm tạo bản sao (copy constructor), cho phép đònh nghiã cách thức tạo các bản sao của các đối tượng (xem chương sau). Bài tập VI 1. Viết chương trình tạo lớp stack trong ví dụ 5.3 chương 2, bổ sung hàm showstack() để truyền một đối tượng kiểu stack. Cho hàm này hiển thò nội dung của ngăn xếp. 2. Tìm lỗi sai trong chương trình này #include <iostream.h> #include <stdlib.h> class dyna { int *p; public: Chửụng 2 Lụựp , ẹ oỏi tửụùng vaứ tớnh ủoựng goựi 53 53 dyna(int i); ~dyna() { free(p); cout << "freeing \n"; } int get() { return *p; } }; dyna::dyna(int i) { p = (int *) malloc(sizeof(int)); if(!p) { cout << "Allocation failure\n"; exit(1); } *p = i; } // Return negative value of *ob.p int neg(dyna ob) { return -ob.get(); } int main() { dyna o(-10); cout << o.get() << "\n"; cout << neg(o) << "\n"; dyna o2(20); cout << o2.get() << "\n"; cout << neg(o2) << "\n"; cout << o.get() << "\n"; cout << neg(o) << "\n"; return 0; . hàng đợi khác. VI/ Truyền các đối tượng sang hàm 1/ Việc truyền các đối tượng cho hàm giống như truyền các đối số thông thường. Tham số của hàm có kiểu dữ. và đối số truyền cho hàm chính là đối tượng . Giống như các kiểu dữ liệu khác, theo ngầm đònh, tất cả các đối tượng được truyền bởi giá trò cho một hàm.

Ngày đăng: 29/09/2013, 07: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