Hàm tạo và hàm hủy
Trong số các phương thức có thể được định nghĩa cho một cấu trúc, có những phương thức đặc biệt: hàm tạo và hàm hủy.
Hàm tạo có cùng tên với tên cấu trúc và không trả về giá trị (kiểu void
). Hàm tạo, nếu được định nghĩa, sẽ được gọi tại thời điểm khởi tạo cho mỗi phiên bản mới của cấu trúc. Do đó, trong hàm tạo, trạng thái ban đầu của cấu trúc có thể được tính toán theo cách đặc biệt.
Một cấu trúc có thể có nhiều hàm tạo với các tập hợp tham số khác nhau, và trình biên dịch sẽ chọn hàm tạo phù hợp dựa trên số lượng và kiểu của các đối số khi định nghĩa biến.
Ví dụ, chúng ta có thể mô tả một cặp hàm tạo trong cấu trúc Result
: một hàm không có tham số, và hàm thứ hai có một tham số kiểu chuỗi để đặt trạng thái.
struct Result
{
...
void Result()
{
status = "ok";
}
void Result(string s)
{
status = s;
}
};
2
3
4
5
6
7
8
9
10
11
12
Nhân tiện, hàm tạo không có tham số được gọi là hàm tạo mặc định. Nếu không có hàm tạo nào được định nghĩa rõ ràng, trình biên dịch sẽ tự động tạo một hàm tạo mặc định cho bất kỳ cấu trúc nào chứa chuỗi hoặc mảng động để điền các trường này bằng số không.
Điều quan trọng là các trường thuộc kiểu khác (ví dụ, tất cả các kiểu số) không được đặt lại về số không, bất kể cấu trúc có hàm tạo mặc định hay không, và do đó các giá trị ban đầu của các phần tử sau khi cấp phát bộ nhớ sẽ là ngẫu nhiên. Bạn nên tạo các hàm tạo hoặc đảm bảo rằng các giá trị đúng được gán trong mã của bạn ngay sau khi đối tượng được tạo.
Sự hiện diện của các hàm tạo rõ ràng khiến việc sử dụng cú pháp khởi tạo tổng hợp trở nên không thể thực hiện được. Vì điều này, dòng Result r = {};
trong phương thức calculate
sẽ không được biên dịch. Bây giờ chúng ta chỉ có quyền sử dụng một trong những hàm tạo mà chúng ta đã cung cấp. Ví dụ, các câu lệnh sau gọi hàm tạo không tham số:
Result r1;
Result r2();
2
Và việc tạo một cấu trúc với trạng thái đã được điền có thể được thực hiện như sau:
Result r3("success");
Hàm tạo mặc định (rõ ràng hoặc ngầm định) cũng được gọi khi một mảng các cấu trúc được tạo. Ví dụ, câu lệnh sau cấp phát bộ nhớ cho 10 cấu trúc với kết quả và khởi tạo chúng bằng hàm tạo mặc định:
Result array[10];
Hàm hủy là một hàm sẽ được gọi khi đối tượng cấu trúc bị hủy. Hàm hủy có cùng tên với tên cấu trúc, nhưng được thêm tiền tố bằng ký tự '~'. Hàm hủy, giống như hàm tạo, không trả về giá trị, nhưng cũng không nhận tham số.
Chỉ có thể có một hàm hủy.
Bạn không thể gọi hàm hủy một cách rõ ràng. Chương trình tự thực hiện điều này khi thoát khỏi một khối mã nơi biến cấu trúc cục bộ được định nghĩa, hoặc khi giải phóng một mảng các cấu trúc.
Mục đích của hàm hủy là giải phóng bất kỳ tài nguyên động nào nếu cấu trúc đã cấp phát chúng trong hàm tạo. Ví dụ, một cấu trúc có thể có thuộc tính persistence
, tức là lưu trạng thái của nó vào một tệp khi nó được dỡ khỏi bộ nhớ và khôi phục lại khi chương trình tạo lại nó. Trong trường hợp này, một mô tả viên cần được mở và đóng được sử dụng trong các hàm tệp tích hợp.
Hãy định nghĩa một hàm hủy trong cấu trúc Result
và thêm các hàm tạo để tất cả các phương thức này theo dõi số lượng phiên bản đối tượng (khi chúng được tạo và hủy).
struct Result
{
...
void Result()
{
static int count = 0;
Print(__FUNCSIG__, " ", ++count);
status = "ok";
}
void Result(string s)
{
static int count = 0;
Print(__FUNCSIG__, " ", ++count);
status = s;
}
void ~Result()
{
static int count = 0;
Print(__FUNCSIG__, " ", ++count);
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Ba biến tĩnh có tên count
tồn tại độc lập với nhau: mỗi biến đếm trong ngữ cảnh của hàm riêng của nó.
Kết quả của việc chạy script, chúng ta sẽ nhận được nhật ký sau:
Result::Result() 1
Result::Result() 2
Result::Result() 3
Result::~Result() 1
Result::~Result() 2
0.5 1 ok
1.00000 2.00000 3.00000
Result::Result(string) 1
0.5 1 ok
1.00000 2.00000 3.00000
Result::~Result() 3
Result::~Result() 4
2
3
4
5
6
7
8
9
10
11
12
Hãy tìm hiểu ý nghĩa của nó.
Phiên bản đầu tiên của cấu trúc được tạo trong hàm OnStart
, trên cùng dòng nơi calculate
được gọi. Khi vào hàm tạo, giá trị đếm count
được khởi tạo một lần với số không và sau đó tăng lên mỗi lần hàm tạo được thực thi, vì vậy lần đầu tiên, giá trị 1 được xuất ra.
Bên trong hàm calculate
, một biến cục bộ kiểu Result
được định nghĩa; nó được đăng ký dưới số 2.
Phiên bản cấu trúc thứ ba không rõ ràng như vậy. Vấn đề là để truyền kết quả từ hàm, trình biên dịch ngầm tạo một biến tạm thời, nơi nó sao chép dữ liệu của biến cục bộ. Có khả năng hành vi này sẽ thay đổi trong tương lai, và sau đó phiên bản cục bộ sẽ "di chuyển" ra khỏi hàm mà không cần sao chép.
Lần gọi hàm tạo cuối cùng nằm trong một phương thức có tham số chuỗi, vì vậy số đếm là 1.
Điều quan trọng là tổng số lần gọi của cả hai hàm tạo bằng với số lần gọi của hàm hủy: 4.
Chúng ta sẽ nói thêm về hàm tạo và hàm hủy trong Chương về Lớp.