1. Trang chủ
  2. » Công Nghệ Thông Tin

Quá tải hàm constructor overloading

32 536 1
Tài liệu đã được kiểm tra trùng lặp

Đ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

Quá tải hàm - tài liệu constructor overloading

Chương 4 Quá tải hàmQuá tải hàm tạo • Hàm tạo bản sao • Hàm với các đối số mặc đònh • Tính không xác đònh khi quá tải hàm • Điạ chỉ của hàm quá tải Chương 4 Quá tải hàm 104 104 Chương 4 Quá tải hàm 105 105 I/ Quá tải hàm tạo (constructor overloading ) Có thể quá tải hàm tạo của một lớp, nhưng không quá tải hàm hủy. Hàm tạo của lớp phải phù hợp với cách mà đối tượng của lớp đó được khai báo. Nếu không lỗi thời gian biên dòch sẽ xảy ra. Có 3 lý do cần quá tải hàm tạo : + để có tính linh hoạt + để hổ trợ mảng + để tạo các hàm tạo bản sao Hạn chế : nếu thực hiện quá tải nhiều lần có thể tạo ra tác dụng hủy hoại trên lớp. • Quá tải hàm tạo với khởi đầu một đối tượng hoặc không khởi đầu đối tượng Ví dụ 1.1 #include <iostream.h> class myclass { int x; public: // overload constructor two ways myclass() { x = 0; } // no initializer myclass(int n) { x = n; } // initializer int getx() { return x; } }; int main() { myclass o1(10); // declare with initial value myclass o2; // declare without initializer cout << "o1: " << o1.getx() << '\n'; cout << "o2: " << o2.getx() << '\n'; return 0; } Chương 4 Quá tải hàm 106 106 • Quá tải hàm tạo để cho các đối tượng riêng lẽ lẫn các mảng đối tượng xảy ra trong chương trình. Ví dụ 1.2 #include <iostream.h> class myclass { int x; public: // overload constructor two ways myclass() { x = 0; } // no initializer myclass(int n) { x = n; } // initializer int getx() { return x; } }; int main() { myclass o1[10]; // declare array without initializers myclass o2[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // declare with initializers int i; for(i=0; i<10; i++) { cout << "o1[" << i << "]: " << o1[i].getx(); cout << '\n'; cout << "o2[" << i << "]: " << o2[i].getx(); cout << '\n'; } return 0; } • Quá tải hàm tạo giúp lập trình viên chọn phương pháp thuận lợi nhất để khởi đầu một đối tượng. Chương 4 Quá tải hàm 107 107 Ví dụ 1.3 #include <iostream.h> #include <stdio.h> // included for sscanf() class date { int day, month, year; public: date(char *str); date (int m, int d, int y) { day = d; month = m; year = y; } void show() { cout << month << '/' << day << '/'; cout << year << '\n'; } }; date::date(char *str) { sscanf(str, "%d%*c%d%*c%d", &month, &day, &year); } int main() { // construct date object using string date sdate("12/31/99"); // construct date object using integers date idate(12, 31, 99); sdate.show(); idate.show(); return 0; } Chương 4 Quá tải hàm 108 108 • Quá tải hàm tạo khi mảng động của lớp được cấp phát. Điều này giúp giải quyết hạn chế trong chương 3, phần IV/2, một mảng động không thể được khởi đầu, xem ví dụ 4.6. Ví dụ 1.4 #include <iostream.h> class myclass { int x; public: // overload constructor two ways myclass() { x = 0; } // no initializer myclass(int n) { x = n; } // initializer int getx() { return x; } void setx(int n) { x = n; } }; int main() { myclass *p; myclass ob(10); // initialize single variable p = new myclass[10]; // can't use initializers here if(!p) { cout << "Allocation error\n"; return 1; } int i; // initialize all elements to ob for(i=0; i<10; i++) p[i] = ob; for(i=0; i<10; i++) { cout << "p[" << i << "]: " << p[i].getx(); cout << '\n'; } Chương 4 Quá tải hàm 109 109 return 0; } Bài tập I 1. Cho lớp sau, hãy bổ sung hai hàm tạo. Hàm tạo thứ nhất không nhận tham số, hàm này dùng toán tử new cấp phát 255 bytes bộ nhớ, khởi đầu bộ nhớ như một chuỗi rỗng và cho len = 255. Hàm tạo thứ hai nhận hai tham số, tham số thứ nhất là chuỗi dùng để khởi đầu và tham số kia là số byte để cấp phát. Cho phiên bản này cấp phát lượng bộ nhớ đã được chỉ rõ và chép chuổi vào bộ nhớ. Thực hiện việc kiểm tra giới hạn biên cần thiết và chứng tỏ các hàm tạo sẽ hoạt động qua một chương trình ngắn. class strtype { char *p; int len; public: char *getstring() { return p; } int getlength() { return len; } }; 2. Từ bài tập II, 2 chương 2, bổ sung hàm tạo không nhận tham số và một phiên bản được quá tải để nhận giờ hệ thống dưới dạng được trả về bởi hàm chuẩn clock(). II/ Tạo và sử dụng hàm tạo bản sao (copy constructor) 1/ Khái niệm Hàm tạo bản sao là kiểu đặc biệt của hàm tạo được quá tải. Khi một đối tượng được truyền cho một hàm, bản sao từng bit một của đối tượng đó được tạo ra và được truyền cho tham số của hàm để nhận đối tượng. Chương 4 Quá tải hàm 110 110 Tuy nhiên, có những trường hợp trong đó bản sao đồng nhất là như không mong muốn. Chẳng hạn, nếu đối tượng có con trỏ tới bộ nhớ được cấp phát, thì bản sao sẽ trỏ tới cùng bộ nhớ như đối tượng gốc đã làm. Do đó, nếu bản sao tạo ra sự thay đổi cho nội dung bộ nhớ thì nó cũng sẽ được thay đổi đối với đối tượng gốc. Khi một hàm kết thúc, bản sao sẽ bò hủy và hàm hủy của nó được gọi. Điều này dẫn đến những tác dụng không mong muốn làm ảnh hưởng đến đối tượng gốc. Khi một đối tượng được trả về từ một hàm tình trạng tương tự cũng sẽ xảy ra. Trình biên dòch sẽ tạo ra một đối tượng tạm để giữ bản sao của giá trò do hàm trả về. Đối tượng tạm này sẽ ra khỏi phạm vi một khi giá trò được trả về cho thủ tục gọi, khiến hàm hủy của đối tượng tạm được gọi. Nếu hàm hủy hủy bỏ thứ gì cần cho thủ tục gọi, chẳng hạn nó giải phóng bộ nhớ cấp phát động, thì rắc rối sẽ xảy ra. Như vậy, cốt lõi của vấn đề trên là bản sao từng bit của đối tượng được tạo ra và thực hiện. Để ngăn chặn vấn đề này, lập trình viên cần xác đònh chính xác những gì xảy ra khi bản sao của một đối tượng được thực hiện để tránh được những tác dụng không mong muốn. Hàm tạo bản sao sẽ giải quyết được vấn đề trên. Khi đònh nghóa hàm tạo bản sao, lập trình viên có thể hoàn toàn kiểm soát chính xác những gì xảy ra khi bản sao của một đối tượng được thực hiện. • Cần phân biệt hai trường hợp trong đó giá trò của một đối tượng được truyền cho đối tượng khác : + Trường hợp thứ nhất là phép gán. + Trường hợp thứ hai là sự khởi đầu, có thể xảy ra theo 3 cách : - Khi một đối tượng được dùng để khởi đầu một đối tượng khác trong câu lệnh khai báo. - Khi một đối tượng được truyền như tham số cho hàm. - Khi một đối tượng tạm được tạo ra dùng để làm giá trò trả về bởi một hàm. Hàm tạo bản sao chỉ áp dụng cho sự khởi đầu. Nó không áp dụng cho phép gán. Hàm tạo bản sao không ảnh hưởng đến các phép gán. Chương 4 Quá tải hàm 111 111 2/ Cú pháp • Dạng tổng quát của hàm tạo bản sao classname(const classname &obj) { // body of constructor } obj là một tham chiếu tới một đối tượng được dùng để khởi đầu một đối tượng khác • Dạng mở rộng của hàm tạo bản sao (có nhiều đối số) classname(const classname &obj, int x = 0) { // body of constructor } Đối số thứ nhất là một tham chiếu tới đối tượng được sao chép, và các đối tượng khác đều mặc đònh. Tính linh hoạt này cho phép tạo ra các hàm tạo bản sao có những công dụng khác. Ví dụ, lớp được gọi là myclass và y là đối tượng của myclass thì các lệnh sau đây sẽ dùng đến hàm tạo bản sao của myclass : myclass x = y; // y explicitly initializing x func1(y); // y passed as a parameter y = func2(); // y receiving a returned object Trong hai trường hợp đầu, một tham chiếu tới y sẽ được truyền cho hàm tạo bản sao. Trường hợp thứ ba, một tham chiếu tới đối tượng được trả về bởi func2() sẽ được truyền cho hàm tạo bản sao. • Tạo một mảng số nguyên "an toàn" có kiểm tra giới hạn biên Ví dụ 2.1 Chương 4 Quá tải hàm 112 112 /* This program creates a "safe" array class. Since space for the array is dynamically allocated, a copy constructor is provided to allocate memory when one array object is used to initialize another. */ #include <iostream.h> #include <stdlib.h> class array { int *p; int size; public: array(int sz) { // constructor p = new int[sz]; if(!p) exit(1); size = sz; cout << "Using 'normal' constructor\n"; } ~array() {delete [] p;} // copy constructor array(const array &a); void put(int i, int j) { if(i>=0 && i<size) p[i] = j; } int get(int i) { return p[i]; } }; /* Copy constructor. In the following, memory is allocated specifically for the copy, and the address of this memory is assigned to p. Therefore, p is not pointing to the same dynamically allocated memory as the original object. */ array::array(const array &a) { [...]... Chương 4 Quá tải hàm • Quá tải hàm tạo • Hàm tạo bản sao • Hàm với các đối số mặc định • Tính không xác định khi quá tải hàm • Điạ chỉ của hàm quá tải Chương 4 Quá tải hàm 105 105 I/ Quá tải hàm tạo ( constructor overloading ) Có thể quá tải hàm tạo của một lớp, nhưng không quá tải hàm hủy. Hàm tạo của lớp phải phù...Chương 4 Quá tải hàm 130 130 V/ Tìm điạ chỉ của một hàm quá tải Trong ngôn ngữ C, để biết điạ chỉ một hàm, dùng con trỏ p trỏ đến hàm đó, chẳng hạn p = zap; // với hàm zap() Trong ngôn ngữ C++, vấn đề hơi phức tạp hơn bởi vì hàm có thể được quá tải. Cơ chế : dùng cách khai báo con trỏ xác định điạ chỉ của hàm quá tải nào sẽ thu được. Hàm có sự phù hợp khai báo là hàm có điạ chỉ... giản để quá tải hàm. • Trong phần trước, một hàm tạo được quá tải chiû cho phép tạo ra các đối tượng được khởi đầu vẫn không được khởi đầu. Trong nhiều trường hợp, có thể tránh quá tải một hàm tạo bằng cách cho nó một hay nhiều đối số ngầm định . Ví duï 3.4 #include <iostream.h> class myclass { int x; public: /* Use default argument instead of overloading myclass's constructor. ... xảy ra. Có 3 lý do cần quá tải hàm tạo : + để có tính linh hoạt + để hổ trợ mảng + để tạo các hàm tạo bản sao Hạn chế : nếu thực hiện quá tải nhiều lần có thể tạo ra tác dụng hủy hoại trên lớp. • Quá tải hàm tạo với khởi đầu một đối tượng hoặc không khởi đầu đối tượng Ví dụ 1.1 #include <iostream.h> class myclass { int x; public: // overload constructor two ways myclass()... định. • Với các đối số mặc định, chúng phải là các hằng hoặc là các biến toàn cục. Chương 4 Quá tải hàm 129 129 • Tính không xác định xảy ra do quá tải hàm, trong đó có một hay nhiều hàm được quá tải dùng một đối số mặc định. Ví dụ 4.4 // Ambiguity based on default arguments plus overloading. #include <iostream.h> int f(int a) { return a*a; } int f(int a,... Chương 4 Quá tải hàm 104 104 Chương 4 Quá tải hàm 111 111 2/ Cú pháp • Dạng tổng quát của hàm tạo bản sao classname( const classname & obj ) { // body of constructor } obj là một tham chiếu tới một đối tượng được dùng để khởi đầu một đối tượng khác • Dạng mở rộng của hàm tạo bản... static int oldcase = ignore; Chương 4 Quá tải hàm 134 134 10. Cho lớp sau đây, có thể cấp phát động một mảng các đối tượng này không ? class test { char *p; int *q; int count; public: test(char *x, int *y, int c) { p = x; q = y; count = c; } // }; Chương 4 Quá tải hàm 132 132 Bài tập chương 4 1. Hãy quá tải hàm tạo date() trong ví dụ 1.3, chương 4 để... noninitialized 10-element array // } 8. Thực hiện quá tải hàm tạo đối với lớp sau đây sao cho các đối tượng không được khởi đầu cũng được tạo ra. class myclass { int x, y; public : myclass(int i, int j) {x= i; y =j;} // } 9. Qua bài tập 8, hãy chứng tỏ có thể không quá tải myclass() bằng cách dùng đối số mặc ñònh. Chương 4 Quá tải hàm 123 123 cout << "o1: "... cout << s << "\n"; } Chương 4 Quá tải hàm 133 133 int x=1, y=0; order(x, y); 6. Tại sao hai hàm quá tải sau vốn không xác định ? int f(int a); int f(int &a); 7. Cho lớp sau, hãy bổ sung các hàm tạo cần thiết để cho cả hai khai báo trong main() đều đúng. class samp { int a; public: // add constructor functions int get_a() { return a; } }; ... cout << c; } int main() { f('c'); f(86) ; // which f() is called??? return 0; } Chương 4 Quá tải hàm 128 128 • Tính không xác định xảy ra do quá tải các hàm, trong đó có sự khác biệt duy nhất là một hàm sử dụng một tham số tham chiếu và hàm kia sử dụng tham số mặc định gọi bằng giá trị. Ví dụ 4.3 // An ambiguous program. #include <iostream.h> . Quá tải hàm • Quá tải hàm tạo • Hàm tạo bản sao • Hàm với các đối số mặc đònh • Tính không xác đònh khi quá tải hàm • Điạ chỉ của hàm quá tải. Chương 4 Quá tải hàm 104 104 Chương 4 Quá tải hàm 105 105 I/ Quá tải hàm tạo (constructor overloading

Ngày đăng: 04/09/2012, 15:12

Xem thêm: Quá tải hàm constructor overloading

TỪ KHÓA LIÊN QUAN

w