2010-09-21 24 views

Trả lời

15

Nếu ngoại lệ được ném trong khi xây dựng, tất cả các đối tượng phụ được tạo trước đó sẽ bị hủy đúng cách. Các chương trình sau đây chứng minh rằng cơ sở chắc chắn bị phá hủy:

struct Base 
{ 
    ~Base() 
    { 
     std::cout << "destroying base\n"; 
    } 
}; 

struct Derived : Base 
{ 
    Derived() 
    { 
     std::cout << "throwing in derived constructor\n"; 
     throw "ooops..."; 
    } 
}; 

int main() 
{ 
    try 
    { 
     Derived x; 
    } 
    catch (...) 
    { 
     throw; 
    } 
} 

đầu ra:

throwing in derived constructor 
destroying base 

(Lưu ý rằng destructor của một con trỏ bản địa không có gì, đó là lý do tại sao chúng ta thích RAII qua con trỏ nguyên.)

+1

Tôi không thể nhớ - nếu bạn không bắt được ngoại lệ, thì trình phá hủy lớp cơ sở được đảm bảo được gọi hoặc được tính là một phần của "thư giãn" và do đó nó được xác định hoặc không phải là một ngoại lệ không bị bắt? –

+0

@Steve: Nếu không có sự bắt, căn cứ không bị phá hủy khi tôi thực hiện, vì vậy tôi * đoán * nó không được bảo đảm, nhưng ai biết ...:-) – fredoverflow

+3

Đó là lý do tại sao nó là một ý tưởng tốt để đặt một nắm bắt và tái ném vào chính để buộc các stack được unwound một cách chính xác. –

9

Có. Quy tắc là mọi đối tượng có hàm tạo đã hoàn tất thành công sẽ bị hủy theo ngoại lệ. Ví dụ:

class A { 
public: 
    ~A() {} 
}; 

class B : public A { 
public: 
    B() { throw 0; } 
    ~B() {} 
}; 

~ A() được gọi. ~ B() không được gọi;

EDIT: hơn nữa, giả sử bạn có các thành viên:

struct A { 
    A(bool t) { if(t) throw 0; } 
    ~A() {} 
}; 

struct B { 
    A x, y, z; 
    B() : x(false), y(true), z(false) {} 
}; 

gì xảy ra là: x được xây dựng, y ném, x là destructed (nhưng không phải y cũng không z).

5

Khi một ngoại lệ được ném ra, các destructors đang kêu gọi tất cả (phụ) đối tượng có nhà xây dựng đã được chạy thành công. Điều này mở rộng cho các thành viên dữ liệu và các lớp cơ sở như nhau.

Ví dụ, đối với mã này

struct base {}; 

struct good {}; 

struct bad { 
    bad() {throw "frxgl!";} 
}; 

struct test : public base { 
    std::string s; 
    good g; 
    bad b; 
    test() {} 
}; 

trước test 's constructor được thực thi, đầu tiên các nhà xây dựng cho lớp cơ sở được gọi, sau đó các nhà thầu cho s, g, và b. Chỉ khi kết thúc thành công, hàm tạo cho test được thực hiện. Khi ngoại lệ được ném trong khi xây dựng b, các trình tạo lớp cơ sở cũng như các hàm tạo cho các thành viên dữ liệu sg đã được thực hiện đầy đủ, do đó các trình phá hủy của chúng được chạy. Hàm khởi tạo của test chính nó và của b chưa được chạy thành công, do đó các trình phá hủy của chúng không chạy.

4

Từ tài liệu chuẩn, 15,3-11,

Các lớp cơ sở xây dựng hoàn chỉnh và các thành viên của một đối tượng sẽ bị hủy diệt trước khi vào xử lý của một hàm try- khối của một nhà xây dựng hoặc destructor cho đối tượng đó.

+1

Trích dẫn hay, nhưng nó không trả lời câu hỏi. – fredoverflow

+0

@FredOverflow, Vâng cảm ơn ... Cập nhật ngay bây giờ .. :) – liaK

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