Tài trợ bài viết này và giới thiệu dịch vụ, sản phẩm, thương hiệu, nhu cầu tuyển dụng của doanh nghiệp đến với cộng đồng.
La Kiến Vinh Để làm rõ hơn về phương thức khởi tạo và phương thức hủy, chỉ cần chỉ rõ hơn về nguồn gốc của nó sẽ giúp cho ta hiểu thấu đáo hơn và dễ sử dụng hơn trong quá trình lập trình, tránh các rủi ro và sự hiểu cứng nhắc trong lập trình với các phương thức này.
Nội dung bài viết

Giới thiệu

Trong bài viết này, tôi trình bày về phương thức tạo và phương thức hủy, chủ yếu là đề cập trong ngôn ngữ C++ nhằm làm rõ hơn vấn đề và ý nghĩa của 2 phương thức này vì nó cũng thường gây bối rối cho nhiều lập trình viên. Sự bối rối này đến từ việc chúng ta không phải là cha đẻ của nó, nên chúng ta không hiểu vì sao nó được tạo ra.

Tôi đã trình bày về 2 phương thức này một phần ở bài viết Sự Ra Đời Của Phương Thức Khởi Tạo (Constructor), Phương Thức Hủy (Destructor) Trong Một Class - C++ và đây là phần kết thúc của việc trình bày 2 vấn đề này.

Vấn đề đồng bộ hóa codes giữa các kiểu dữ liệu

Xét ví dụ sau với một biến int primitiveType

void func()
{
	// INIT VARIABLE
	int primitiveType = 0;
	
	// DO SOMETHING
	
	// DONE
}

Biến primitiveType theo lý thuyết được cấp phát khi vào hàm func và được thu hồi khi hàm func thực thi xong. Mọi thứ liên quan đến biến này sẽ được dọn dẹp trong bộ nhớ.

Đối với một Object, mọi việc phức tạp hơn 1 chút vì bản thân Object chứa đựng những thuộc tính bên trong nó, một ví dụ điển hình nhất là nếu thuộc tính của Object là một dạng pointer và có cấp phát động cho pointer này. Ta cần lưu ý thu hồi vùng nhớ đó trước khi Object bị hủy, ta phải hiện thực thêm phương thức Destroy (phương thức này có nhiệm vụ là delete toàn bộ các vùng nhớ pointer đang quản lý) trong class của Object đó và gọi nó trước khi func kết thúc. Ta sẽ có code như sau.

void func()
{
	// INIT VARIABLE
	Object obj = 0;
	
	// DO SOMETHING
	
	// DONE
	obj.Destroy();
}

Cách làm này sẽ mang đến sự không đồng bộ nếu ta dùng 1 dạng kiểu dữ liệu cơ bản như ví dụ bên trên int primitiveType khi mà trong code xuất hiện thêm dòng obj.Destroy().

Để đồng bộ được tư tưởng này, tránh gọi thêm các phương thức, kỹ thuật hỗ trợ thêm cho ta khái niệm Destructor và ta chỉ cần hiện thực bên trong đó việc thu hồi các vùng nhớ cấp phát động trước khi đối tượng bị hủy.

Giả sử ta đã thiết kế sẵn việc delete các vùng nhớ do các pointer của class Object trong Destructor, lúc này ta chỉ việc Code như 1 dạng dữ liệu primitive (kiểu dữ liệu dựng sẵn như int, char, ...).

void func()
{
	// INIT VARIABLE
	Object obj = 0;
	
	// DO SOMETHING
	
	// DONE

}

Lưu ý

Việc sử dụng Constructor và Destructor không phải là việc bắt buộc trong lập trình với OOP miễn là bạn có thể đảm bảo được việc cấp phát hoặc thu hồi đầy đủ nhất có thể.

THẢO LUẬN
ĐÓNG