Hàm khởi tạo và hủy bỏ
Trong C++, sự khởi tạo la một quá trìnhquan trọng đối với người lập trình. Người thiết kế lớpcó thể bảo đảm lớp cho mỗi đối tượng bằng việc cungcấp một hàm được gọi la hàm khởi tạo.
trình biên dịchtự động gọi hàm khởi tạo đó tại vị trí một đối tượngđược cài đặt trước khi người lập trinh có thể tiếnhành trên đối tượng.
SEMINAR 1Vũ Trọng Đắc: 08520088Trần Quốc Công: 08520046 THINKING IN C++. CHAPTER 6 HÀM KHỞI TẠO VÀ HỦY BỎ 1.VIỆC KHỞI TẠO ĐƯỢC ĐẢM BẢO VỚI HÀMKHỞI TẠO Trong C++, sự khởi tạo la một quá trìnhquan trọng đối với người lập trình. Người thiết kế lớpcó thể bảo đảm lớp cho mỗi đối tượng bằng việc cungcấp một hàm được gọi la hàm khởi tạo. trình biên dịchtự động gọi hàm khởi tạo đó tại vị trí một đối tượngđược cài đặt trước khi người lập trinh có thể tiếnhành trên đối tượng. Tiếp theo là làm gì để gọi tên hàm này: có hai cách giải quyết: Thứ nhất là có nhiều tên bạn dùng,có một vài tên trùng với một tên bạn có thể lựachọn để sử dụng như là một thành viên trong lớp. Đây là một ví dụ lớp với hàm khởi tạo: class X{ int i; public: X( );//constructor }; Bây giờ khi một đối tượng được định nghĩa: Void f( ){ X a; //… } Khi chương trình băt đầu thực hiện tới vị trí nơi mà a đươc định nghĩa thì hàm khởi tạo đươc gọi một cáchtự động. Trình biên dịch tự nhiên chèn vào lời gọiđến X::X( ) cho đối tượng a tại vị trí định nghĩa. Như nhiều hàm thành viên, luận cứ đàu tiên cho hàm khởitạo la this , địa chỉ của đối tượng cho cái đang đượcgọi. Cả hàm khởi tạo và hủy bỏ là những hàm rất đặc biệt, chúng không trả về giá trị. Đây là sự khác biệt rõ ràng so với hàm void Nếu có một giá trị trả về và nếu bạn có thể chọn cho chính bạn trình biêndịch sẽ không biết phải làm gì với giá trị trả về đó vàngười lập trình tất nhiên sẽ phải gọi những hàm khởi tạo hoặc hủy bỏ. 2.XÓA BỎ AN TOÀN VỚI HÀM HỦY BỎ Trong C++, việc xóa bỏ thì quan trọngnhư việc khởi tạo và bởi vậy nên phải được đảm bảovới ham hủy bỏ. Sự hủy bỏ thì được phân biệt với hàm khởi tạo bởi một dấu ngã (~). Đây là sự khaibáo cho một hàm hủy bỏ: class Y{ public : ~ Y; }; Hàm hủy bỏ thì được gọi một cách tự động bởitrình biên dịch khi đối tượng thoát ra khỏi phạm vi. Bạn sẽ thấy nơi hàm khởi tạo tại vị trí mà đối tượngđược định nghĩa, nhưng dấu hiệu cho việc gọi hàm khởi tạo la việc đóng dấu ngoặc } //: C06:Constructor1.cpp // Constructors & destructors #include using namespace std; class Tree { int height; public: Tree(int initialHeight); // Constructor ~Tree(); // Destructor void grow(int years); void printsize(); }; Tree::Tree(int initialHeight) { height = initialHeight; } Tree::~Tree() { cout #include using namespace std; class G { int i; public: G(int ii); }; G::G(int ii) { i = ii; } int main() { cout > retval; require(retval != 0); int y = retval + 3; G g(y); } ///:~ Vòng lặp for Trong C++, ban thường thấy một vòng for được định nghĩa đúng như sau: for(int j = 0; j < 100; j++) { cout << "j = " << j << endl; } for(int i = 0; i < 100; i++) cout << "i = " << i << endl; SỰ CẤP PHÁT VÙNG NHỚ Một biến số bây giờ có thể được định nghĩa tại nhiều vị trí trong khối, vì vậy nó dường như có thể rằng vùng nhớ cho một biến số có thể không đươc đinh nghĩa đến khi điểm định nghĩa của nó. Người lập trình không thể truy nhập vùng nhớ đến khi nó được định nghĩa . Trình biên dịch vẫn kiểm tra để chắc chắn rằng bạn không đặt những đối tượng định nghĩa ơ nơi mà chuỗi vị trí chỉ có điều kiện chuyển qua nó, như trong hàm swich hoặc ở một nơi mà goto nhảy qua nó. Việc không đề cập đến sự trình bày theo sau code sẽ phát sinh một cảnh báo hoặc lỗi. // Can't jump past constructors class X { public: X(); }; X::X() {} void f(int i) { if(i < 10) { //! goto jump1; // Error: goto bypasses init } X x1; // Constructor called here jump1: switch(i) { case 1 : X x2; // Constructor called here break; //! case 2 : // Error: case bypasses init X x3; // Constructor called here break; } } int main() { f(9); f(11); }///:~ Khởi tạo khối tập hợp Một khối tập hợp thì giống như là một lượng nhóm lại với nhau.Định nghĩa này bao gồm cả khối tập hợp các kiểu nhóm chung với nhau, như là class và struct. Một mảng là một khối tập hợp nhưng cùng một kiểu dữ liệu. Ví dụ cho một mảng tĩnh: int a[5] = { 1, 2, 3, 4, 5 }; Khởi tạo khối tập hợp Nếu ta khởi tạo hơn số thành phần của mảng, trình biên dịch sẽ thông báo lỗi. Nếu khởi tạo ít hơn thì sao? Ví dụ: int b[6] = {1}; Trình biên dịch sẽ gán giá trị đầu tiên cho phần tử đầu tiên của mảng,và gán 0 cho tất cả những phần tử mảng còn lại. Điều này sẽ không xảy ra nếu ta định rõ một mảng mà không khởi tạo. Ví dụ: int b[6]; Khởi tạo khối tập hợp Khả năng ”tự động đếm”, trong đó trình biên dịch sẽ xác định kích thước mảng dựa trên các số được khởi tạo: int c[] = { 1, 2, 3, 4 }; Nếu bạn muốn tăng số phần tử của mảng, hãy thêm giá trị khởi tạo khác. Khởi tạo khối tập hợp Một struct trong C có những thành viên là dạng public, nên chúng có thể được tạo một cách trực tiếp: struct X { int i; float f; char c; }; X x1 = { 1, 2.2, 'c' }; Khởi tạo khối tập hợp Nếu bạn có một mảng như các đối tượng, bạn có thể khởi tạo cho chúng bằng cách dùng:X x2[3] = { {1, 1.1, 'a'}, {2, 2.2, 'b'} }; Ở ví dụ trên, đối tượng thứ 3 sẽ được gán là 0. Khởi tạo khối tập hợp Một struct như sau: struct Y { float f; int i; Y(int a); }; Bạn phải chỉ rõ hàm tạo gọi.Cách tốt nhất là: Y y1[] = { Y(1), Y(2), Y(3) }; Bất kể là một struct với thành phần public hay một class với thành phần dữ liệu private, tất cả những sự khởi tạo phải thông qua hàm tạo. Hàm tạo mặc định Một hàm tạo mặc định là một hàm tạo được gọi mà không có đối số. Một hàm tạo mặc định được tạo ra khi trình biên dịch tạo ra một đối tượng nhưng không đưa vào bất kì chi tiết nào. Hàm tạo mặc định này không làm gì cả. Hàm tạo mặc định Hãy nhớ, nếu bạn có một hàm tạo, trình biên dịch sẽ luôn tạo giá trị dù trong bất kì tình huống nào. Hàm tạo mặc định rất quan trọng, nếu không có một hàm tạo cho một structure(struct hay class), trình biên dịch sẽ tự động tạo nó cho bạn. // Automatically-generated default constructor class V { int i; // private }; // No constructor int main() { V v, v2[10]; } ///:~ Hàm tạo mặc định Nếu có một hàm tạo được định nghĩa, thì sẽ không có hàm tạo mặc định. Mặc dù trình biên dịch sẽ tạo một hàm tạo mặc định cho bạn, nhưng bộ khởi tạo này thường không phải điều bạn muốn.Vì vậy bạn nên cẩn thận khi thực hiện nó.Nói chung, bạn nên định nghĩa hàm tạo một cách rõ ràng và không nên để trình biên dịch làm điều đó. SUMARRY Một trong những vấn mà C++ cải tiến từ C chính là việc khởi tạo giá trị.Và một trong những lỗi khó phát hiện chính là việc giải phóng bộ nhớ không đúng cách. Vì vậy, C++ cho phép xây dựng hàm tạo và hàm hủy, điều này giúp việc khởi tạo và giải phóng bộ nhớ một cách thích hợp. Việc tạo và hủy là một trong những phần quan trọng giúp cho chương trình thực hiện trơn tru hơn trong C++.
File đính kèm:
- Hàm khởi tạo và hủy bỏ.ppt