2009-03-17 9 views

Trả lời

49

Trình tự là:

  1. cơ sở constructor
  2. constructor nguồn gốc
  3. nguồn gốc destructor
  4. cơ sở destructor

Ví dụ:

class B 
{ 
public: 
    B() 
    { 
    cout<<"Construct B"<<endl; 
    } 

    virtual ~B() 
    { 
    cout<<"Destruct B"<<endl; 
    } 
}; 

class D : public B 
{ 
public: 
    D() 
    { 
    cout<<"Construct D"<<endl; 
    } 

    virtual ~D() 
    { 
    cout<<"Destruct D"<<endl; 
    } 
}; 



int main(int argc, char **argv) 
{ 
    D d; 
    return 0; 
} 

Sản lượng Ví dụ:

Construct B

Construct D

Destruct D

Destruct B

Nhiều mức độ thừa kế hoạt động giống như một chồng:

Nếu bạn xem xét đẩy một mục vào stack như xây dựng, và lấy nó ra như phá hủy, sau đó bạn có thể nhìn ở nhiều cấp độ thừa kế như một chồng.

Điều này phù hợp với mọi cấp độ.

Ví dụ D2 xuất phát từ D xuất phát từ B.

Đẩy B trên stack, đẩy D trên stack, đẩy D2 trên stack. Vì vậy, thứ tự xây dựng là B, D, D2. Sau đó, để tìm ra thứ tự hủy diệt bắt đầu xuất hiện. D2, D, B

ví dụ phức tạp hơn:

Đối với ví dụ phức tạp hơn, xin vui lòng xem liên kết được cung cấp bởi @JaredPar

+1

Có thể OP muốn biết về lớp D: công khai A, B, C ... –

+1

Nhiều thừa kế thêm một số phức tạp: http://www.gotw.ca/gotw/080.htm –

9

Ngoài ra, hãy nhớ rằng trong khi các phần tử mảng được xây dựng đầu tiên -> cuối cùng, họ được destructed theo thứ tự ngược lại: cuối cùng -> đầu tiên.

+1

+1 Điều đó đúng với hầu hết mọi thứ. Thứ tự hủy diệt luôn luôn là trái ngược với xây dựng. Các biến tĩnh không có thứ tự xây dựng được đảm bảo, nhưng sự phá hủy sẽ xảy ra theo thứ tự đảo ngược. –

+0

Đó có phải là hành vi chứa container (dự kiến) và/hoặc hành vi 'mới []'/'xóa []' được xây dựng? – franji1

2

tôi phải thêm vào các câu trả lời trước vì tất cả mọi người dường như bị bỏ qua nó

Khi bạn có một có nguồn gốc lớp dụ là tạo, đúng là mã bên các nhà xây dựng của các cơ sở sẽ được gọi trướcbên constructor của có nguồn gốc, nhưng hãy nhớ rằng có nguồn gốc vẫn là kỹ thuật "tạo ra"trước các cơ sở.

Và khi bạn có có nguồn gốc lớp destructor được gọi, đó là sự thật rằng mã bên destructor có nguồn gốc được gọi là trướcbên destructor cơ sở, mà còn giữ lưu ý rằng cơ sở bị phá hủytrướccó nguồn gốc.

Khi tôi nói đã tạo/hủy Tôi thực sự đang đề cập đến được phân bổ/deallocated.

Nếu bạn nhìn vào bố cục bộ nhớ của các trường hợp này, bạn sẽ thấy rằng thể hiện được bắt nguồn soạn phiên bản cơ sở. Ví dụ:

Memory của nguồn gốc: 0x00001110 để 0x00001120

Memory của cơ sở: 0x00001114 để 0x00001118

Do đó, lớp được thừa kế phải được phân bổ TRƯỚC cơ sở trong việc xây dựng. Và lớp dẫn xuất phải được deallocated SAU cơ sở trong sự hủy diệt.

Nếu bạn có đoạn mã sau:

class Base 
{ 
public: 
    Base() 
    { 
     std::cout << "\n Base created"; 
    } 
    virtual ~Base() 
    { 
     std::cout << "\n Base destroyed"; 
    } 
} 

class Derived : public Base 
{ 
public: 
    Derived() 
    // Derived is allocated here 
    // then Base constructor is called to allocate base and prepare it 
    { 
     std::cout << "\n Derived created"; 
    } 
    ~Derived() 
    { 
     std::cout << "\n Derived destroyed"; 
    } 
    // Base destructor is called here 
    // then Derived is deallocated 
} 

Vì vậy, nếu bạn đã tạo Derived d; và đã có nó đi ra khỏi phạm vi, sau đó bạn sẽ nhận được đầu ra trong @ câu trả lời của Brian.Tuy nhiên, hành vi của đối tượng trong bộ nhớ là không thực sự là trong cùng một thứ tự, nó là nhiều như thế này:

xây dựng:

  1. bắt nguồn phân bổ

  2. cơ sở phân bổ constructor

  3. cơ sở gọi là

  4. Nhà xây dựng có nguồn gốc được gọi là

Tiêu hủy:

  1. destructor nguồn gốc gọi

  2. cơ sở destructor được gọi là

  3. cơ sở deallocated

  4. nguồn gốc deallocated