2012-10-04 47 views
6

thể trùng lặp:
How to clean initialized resources if exception thrown from constructor in c++Làm cách nào để xử lý đúng ngoại lệ trong các nhà xây dựng?

Làm thế nào để xử lý ngoại lệ trong nhà thầu nếu tôi đang tạo ra 6 đối tượng và các đối tượng tạo 5 đối tượng và thất bại trong khi tạo ra một thứ 6?

Cảm ơn.

+3

Làm thế nào về liên kết, mà Als cung cấp cho bạn ở đây http://stackoverflow.com/questions/12723492/how-to-clean-initialized-resources-if-exception-thrown-from-constructor-in-c? Thành viên này có phải là đối tượng không? – ForEveR

+0

Bạn cần xử lý gì? Thông thường, bạn chỉ đơn giản là để cho các ngoại lệ tuyên truyền, để 5 đối tượng đầu tiên bị tiêu diệt một cách sạch sẽ. Một số ngữ cảnh khác sẽ hữu ích – jalf

+0

RAII. (Http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) – ScaryAardvark

Trả lời

1

Khi ngoại lệ được ném vào hàm khởi tạo, tất cả các lớp con được xây dựng hoàn chỉnh đều bị hủy. Vì nó là thực hành tốt để có destructors của các đối tượng xây dựng xem xét sau khi resoyrces của họ, không có gì cần phải được thực hiện cho các subobjects. Những gì còn lại là làm sạch trong cơ thể của các nhà xây dựng hiện đang thực hiện khi ngoại lệ được ném. Tuy nhiên, điều này không khác với việc dọn dẹp ở bất kỳ chức năng nào khác.

Lưu ý rằng thứ tự hủy là mặt sau của công trình. Nghĩa là, làm sạch trong cơ thể bắt đầu trước khi tất cả các subobjects không, nhưng, bị phá hủy. Sau đó, các thành viên bị phá hủy, sau đó các lớp cơ sở không ảo, và cuối cùng là các lớp cơ sở ảo.

3

Hành vi thông thường chỉ là để tuyên truyền ngoại lệ. Destructors cho bất kỳ lớp học cơ sở hoàn toàn được xây dựng và các thành viên sẽ được gọi; nếu năm đối tượng đầu tiên là thành viên, chúng sẽ được chính xác bị hủy.

Trường hợp duy nhất mà sự cố có thể xảy ra là nếu đối tượng bạn đang nói về đã được phân bổ động (sử dụng new). Nếu đó là trường hợp: điều đầu tiên để tự hỏi mình là lý do tại sao? Tại sao bạn lại phân bổ động và không làm cho đối tượng trở thành thành viên cụ thể? Trong kinh nghiệm của tôi, nhu cầu đó rất, rất hiếm, ngoại trừ trong một số trường hợp đặc biệt (ví dụ thành ngữ tường lửa biên dịch), trong trường hợp này, sẽ có thường là một đối tượng trong lớp (ví dụ: con trỏ đến đối tượng triển khai). Trong những trường hợp như vậy, không có vấn đề gì, bởi vì nếu các new của đối tượng đó không thành công, không có gì khác đã được thực hiện cần hoàn tác.

Nếu bạn thấy mình trong trường hợp đặc biệt hiếm hoi mà bạn thực sự làm phải sử dụng phân bổ động có nhiều hơn một đối tượng như vậy (ví dụ bởi vì bạn có hai subobjects mà là đa hình), sau đó bạn sẽ phải đảm bảo rằng mỗi phân bổ được gói trong một số loại của một đối tượng phụ (một con trỏ thông minh sẽ thực hiện thủ thuật); khi đối tượng phụ đầu tiên đã được xây dựng thành công, hàm hủy của nó sẽ là được gọi nếu hàm tạo không thành công tại một số điểm sau này.

1

Tại "lõi" đối phó với các ngoại lệ là hầu như mọi thứ nên được dọn sạch thông qua các trình phá hủy. Ví dụ, nếu bạn "mới" một đối tượng bạn nhận được một con trỏ "thô"; nếu một ngoại lệ được ném ra một nơi nào đó, bạn phải chắc chắn rằng con trỏ thô này là đúng "xóa" d - nhưng chắc chắn rằng bạn không xóa một con trỏ thô chưa được khởi tạo.

Mặt khác, nếu bạn lưu con trỏ đó vào một tiêu chuẩn :: unique_ptr bạn không phải làm gì cả; khi unique_ptr bị hủy, đối tượng sẽ bị xóa, và sự phá hủy đối tượng xảy ra tự động: khi unique_ptr đi ra khỏi phạm vi, trình biên dịch sẽ gọi dọn dẹp, hoàn toàn vô hình (vì vậy không có nhiều mã lộn xộn với tấn cuộc gọi dọn dẹp) và tự động (như vậy không còn 'ouch, khi nó có con đường hiếm hoi mà không ai thực sự thử nghiệm nó quên để dọn dẹp').

Điều tương tự cũng có thể áp dụng cho mọi tài nguyên; có "các con trỏ tự động" cho các đối tượng COM (như được sử dụng trong DirectX), hầu hết các khung công tác sẽ cung cấp cho bạn một đối tượng kiểu "scoped lock" để bao quanh các mutex (vì vậy nó khóa mutex khi đối tượng được tạo và mở khóa khi nó bị phá hủy) và bạn có thể viết các trình bao bọc nhỏ để xử lý các trình xử lý Windows khác nhau.

Về cơ bản, nếu bạn đặt tất cả việc dọn dẹp của bạn vào các trình phá hủy, bạn sẽ không bao giờ phải "thử ... bắt ... rethrow" chỉ để làm sạch. Và destructors của "lớn hơn" đối tượng thường sẽ rất đơn giản, như hầu như tất cả các "chứa" đối tượng được làm sạch tự động bởi destructors của họ.

Các vấn đề liên quan