構造和解構函式呼叫順序
參考文章:
一. 理論
1. 建構函式和解構函式
①建構函式
- 建構函式不能有返回值
- 預設建構函式時,系統將自動呼叫該預設建構函式初始化物件,預設建構函式會將所有資料成員都初始化為零或空
- 建立一個物件時,系統自動呼叫建構函式
②解構函式
- 解構函式沒有引數,也沒有返回值。不能過載,也就是說,一個類中只可能定義一個解構函式
- 如果一個類中沒有定義解構函式,系統也會自動生成一個預設的解構函式,為空函式,什麼都不做
- 呼叫條件:1.在函式體內定義的物件,當函式執行結束時,該物件所在類的解構函式會被自動呼叫;2.用new運算子動態構建的物件,在使用delete運算子釋放它時。
③拷貝建構函式
- 拷貝建構函式實際上也是建構函式,具有一般建構函式的所有特性,其名字也與所屬類名相同。拷貝建構函式中只有一個引數,這個引數是對某個同類物件的引用。它在三種情況下被呼叫:
- 用類的一個已知的物件去初始化該類的另一個物件時;
- 函式的形參是類的物件,呼叫函式進行形參和實參的結合時;
- 函式的返回值是類的物件,函式執行完返回撥用者。
2. 建構函式的呼叫順序
基類建構函式、物件成員建構函式、派生類本身的建構函式
3. 解構函式的呼叫順序
派生類本身的解構函式、物件成員解構函式、基類解構函式(與構造順序正好相反)
4. 特例
區域性物件,在退出程式塊時析構
靜態物件,在定義所在檔案結束時析構
全域性物件,在程式結束時析構
繼承物件,先析構派生類,再析構父類
物件成員,先析構類物件,再析構物件成員
二. 例子
#include <iostream>
using namespace std;
class Base1
{
public:
Base1(void){cnt++;cout<<"Base1::constructor("<<cnt<<")"<<endl;}
~Base1(void){cnt--;cout<<"Base1::deconstructor("<<cnt + 1<<")"<<endl;}
private:
static int cnt;
};
int Base1::cnt = 0;
class Base2
{
public:
Base2(int m){num = m; cout<<"Base2::constructor("<<num<<")"<<endl;}
~Base2(void){cout<<"Base2::deconstructor("<<num<<")"<<endl;}
private:
int num;
};
class Example
{
public:
Example(int n){num = n; cout<<"Example::constructor("<<num<<")"<<endl;}
~Example(void){cout<<"Example::deconstructor("<<num<<")"<<endl;}
private:
int num;
};
class Derived:public Base1, public Base2
{
public:
Derived(int m, int n):Base2(m),ex(n){cnt++;cout<<"Derived::constructor("<<cnt<<")"<<endl;}
~Derived(void){cnt--;cout<<"Derived::deconstructor("<<cnt+1<<")"<<endl;}
private:
Example ex;
static Example stex; //Example::constructor(1) //不能輸出
static int cnt;
};
int Derived::cnt = 0;
Derived ge_a(1,2); // Base1::constructor(1)
// Base2::constructor(1)
// Example::constructor(2)
// Derived::constructor(1)
static Derived gs_b(3,4); // Base1::constructor(2)
// Base2::constructor(3)
// Example::constructor(4)
// Derived::constructor(2)
int main(void)
{
cout << "---------start---------" << endl;
Derived d(5,6); // Base1::constructor(3)
// Base2::constructor(5)
// Example::constructor(6)
// Derived::constructor(3)
Derived e(7,8); // Base1::constructor(4)
// Base2::constructor(7)
// Example::constructor(8)
// Derived::constructor(4)
cout << "----------end----------" << endl;
//Derived e(7,8) 析構
// Derived::deconstructor(4)
// Example::deconstructor(8)
// Base2::deconstructor(7)
// Base1::deconstructor(4)
//Derived d(5,6) 析構
// Derived::deconstructor(3)
// Example::deconstructor(6)
// Base2::deconstructor(5)
// Base1::deconstructor(3)
return 0;
}
//static Derived gs_b(3,4) 析構
// Derived::deconstructor(2)
// Example::deconstructor(4)
// Base2::deconstructor(3)
// Base1::deconstructor(2)
//Derived ge_a(1,2) 析構
// Derived::deconstructor(1)
// Example::deconstructor(2)
// Base2::deconstructor(1)
// Base1::deconstructor(1)
//static Example stex 析構
//Example::deconstructor(1) //不能輸出
#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"A::constructor"<<endl;};
~A(){cout<<"A::deconstructor"<<endl;};
};
class B
{
public:
B(){cout<<"B::constructor"<<endl;};
~B(){cout<<"B::deconstructor"<<endl;};
};
class C : public A
{
public:
C(){cout<<"C::constructor"<<endl;};
~C(){cout<<"C::deconstructor"<<endl;};
private:
// static B b;
B b;
};
class D : public C
{
public:
D(){cout<<"D::constructor"<<endl;};
~D(){cout<<"D::deconstructor"<<endl;};
};
int main(void)
{
C* pd = new D();
delete pd;
return 0;
}
/* Output
----->B b
A::constructor
B::constructor
C::constructor
D::constructor
C::deconstructor
B::deconstructor
A::deconstructor
----->static B b
A::constructor
C::constructor
D::constructor
C::deconstructor
A::deconstructor
*/
相關文章
- [C++]顯示呼叫建構函式和解構函式C++函式
- C++ 建構函式和解構函式C++函式
- 類的建構函式和解構函式函式
- C++建構函式和解構函式呼叫虛擬函式時使用靜態聯編C++函式
- C++ 類建構函式和解構函式C++函式
- 第八章:不要在構造和解構函式中使用虛擬函式函式
- 直譯器構造實現函式呼叫函式
- static程式碼塊、構造程式碼塊、建構函式以及Java類初始化順序C程式函式Java
- C++建構函式初始化順序C++函式
- C++入門記-建構函式和解構函式C++函式
- c#構造初使化的順序C#
- 建立派生類物件,建構函式的執行順序物件函式
- Servlet呼叫構造方法,物件傳不進建構函式中去問題Servlet構造方法物件函式
- 構造java函式(轉)Java函式
- Objective-C學習筆記---建構函式和解構函式Object筆記函式
- 順序結構
- GC和解構函式(Finalize 方法)GC函式
- C/C++——建構函式、複製建構函式和解構函式的執行時刻C++函式
- toString()和valueOf()函式呼叫和優先順序函式
- ASP.NET Page函式呼叫順序及解釋ASP.NET函式
- (C++通訊架構學習筆記):日誌列印、優化main函式呼叫順序C++架構筆記優化AI函式
- c# tcbs之建構函式呼叫建構函式示例C#函式
- 繼承與派生,多繼承,函式過載,建構函式呼叫順序 靜態多型和動態多型繼承函式多型
- Java static變數、作用域、建構函式初始化順序Java變數函式
- C++知識點49——類繼承與類的構造、拷貝、operator=和解構函式C++繼承函式
- C++ 建構函式實戰指南:預設構造、帶引數構造、複製構造與移動構造C++函式
- C#的IDisposable 介面和解構函式C#函式
- PHP 手冊 (類與物件) 學習筆記五:建構函式和解構函式PHP物件筆記函式
- 第4周課後實踐·閱讀程式-建構函式和解構函式(2)函式
- 第4周課後實踐·閱讀程式-建構函式和解構函式(3)函式
- 第4周課後實踐·閱讀程式-建構函式和解構函式(4)函式
- 順序結構與選擇結構
- 建構函式之間的呼叫函式
- Java中構造方法,構造程式碼塊和靜態程式碼塊執行順序詳解Java構造方法
- 區分:派生類指定基類建構函式、繼承構造、委託構造函式繼承
- 構造解構函式的妙用-成對出現 (轉)函式
- C++箴言:避免解構函式呼叫虛擬函式C++箴言函式
- Java的預設建構函式呼叫Java函式