文章目錄
- 2.2解構函式
- 2.3拷貝建構函式
- 4.1代碼
- 4.2運行結果
- 4.3結果解析
- 5.1代碼
- 5.2運行結果
- 5.3說明
1.參考文獻
參考1: C++繼承中建構函式、解構函式調用順序及虛函數的動態綁定
參考2: 建構函式、拷貝建構函式和解構函式的的調用時刻及調用順序
參考3: C++建構函式與解構函式的調用順序
2.建構函式、解構函式與拷貝建構函式介紹2.1建構函式
- 建構函式不能有傳回值
- 預設建構函式時,系統將自動調用該預設建構函式初始化對象,預設建構函式會將所有資料成員都初始化為零或空
- 建立一個對象時,系統自動調用建構函式
2.2解構函式
- 解構函式沒有參數,也沒有傳回值。不能重載,也就是說,一個類中只可能定義一個解構函式
- 如果一個類中沒有定義解構函式,系統也會自動產生一個預設的解構函式,為空白函數,什麼都不做
- 調用條件:1.在函數體內定義的對象,當函數執行結束時,該對象所在類的解構函式會被自動調用;2.用new運算子動態構建的對象,在使用delete運算子釋放它時。
2.3拷貝建構函式
拷貝建構函式實際上也是建構函式,具有一般建構函式的所有特性,其名字也與所屬類名相同。拷貝建構函式中只有一個參數,這個參數是對某個同類對象的引用。它在三種情況下被調用:
- 用類的一個已知的對象去初始化該類的另一個對象時;
- 函數的形參是類的對象,調用函數進行形參和實參的結合時;
- 函數的傳回值是類的對象,函數執行完返回調用者。
3.建構函式與解構函式的調用順序對象是由“底層向上”開始構造的,當建立一個對象時,首先調用基類的建構函式,然後調用下一個衍生類別的建構函式,依次類推,直至到達衍生類別次數最多的派生次數最多的類的建構函式為止。因為,建構函式一開始構造時,總是要調用它的基類的建構函式,然後才開始執行其建構函式體,調用直接基類建構函式時,如果無專門說明,就調用直接基類的預設建構函式。在對象析構時,其順序正好相反。4.執行個體14.1代碼View Code
#include<iostream>using namespace std;class point{private: int x,y;//資料成員public: point(int xx=0,int yy=0)//建構函式 { x=xx; y=yy; cout<<"建構函式被調用"<<endl; } point(point &p);//拷貝建構函式,參數是對象的引用 ~point(){cout<<"解構函式被調用"<<endl;} int get_x(){return x;}//方法 int get_y(){return y;}};point::point(point &p){ x=p.x;//將對象p的變相賦值給當前成員變數。 y=p.y; cout<<"拷貝建構函式被調用"<<endl;}void f(point p){ cout<<p.get_x()<<" "<<p.get_y()<<endl;}point g()//傳回型別是point{ point a(7,33); return a;}void main(){ point a(15,22); point b(a);//構造一個對象,使用拷貝建構函式。 cout<<b.get_x()<<" "<<b.get_y()<<endl; f(b); b=g(); cout<<b.get_x()<<" "<<b.get_y()<<endl;}
4.2運行結果
4.3結果解析建構函式被調用 //point a(15,22);
拷貝建構函式被調用//point b(a);拷貝建構函式的第一種調用情況:
用類的一個已知的對象去初始化該類的另一個對象時
15 22//cout<<b.get_x()<<" "<<b.get_y()<<endl;拷貝建構函式被調用//f(b);拷貝建構函式的第二種調用情況:
函數的形參是類的對象,調用函數進行形參和實參的結合時
15 22 //void f(point p)函數輸出對象b的成員
解構函式被調用//f(b);解構函式的第一種調用情況:
在函數體內定義的對象,當函數執行結束時,該對象所在類的解構函式會被自動調用
建構函式被調用//b=g();的函數體內point a(7,33);建立對象a
拷貝建構函式被調用//b=g();拷貝建構函式的第三種調用情況,拷貝a的值賦給b:
函數的傳回值是類的對象,函數執行完返回調用者
解構函式被調用//拷貝建構函式對應的解構函式
解構函式被調用//b=g();的函數體內對象a析構
7 33
解構函式被調用//主函數體b對象的析構
解構函式被調用//主函數體a對象的析構5.執行個體25.1代碼View Code
#include <iostream>using namespace std;//基類class CPerson{ char *name; //姓名 int age; //年齡 char *add; //地址public: CPerson(){cout<<"constructor - CPerson! "<<endl;} ~CPerson(){cout<<"deconstructor - CPerson! "<<endl;}};//衍生類別(學生類)class CStudent : public CPerson{ char *depart; //學生所在的系 int grade; //年級public: CStudent(){cout<<"constructor - CStudent! "<<endl;} ~CStudent(){cout<<"deconstructor - CStudent! "<<endl;}};//衍生類別(教師類)//class CTeacher : public CPerson//繼承CPerson類,兩層結構class CTeacher : public CStudent//繼承CStudent類,三層結構{ char *major; //教師專業 float salary; //教師的工資public: CTeacher(){cout<<"constructor - CTeacher! "<<endl;} ~CTeacher(){cout<<"deconstructor - CTeacher! "<<endl;}};//實驗主程式void main(){ //CPerson person; //CStudent student; CTeacher teacher;}
5.2運行結果
5.3說明在執行個體2中,CPerson是CStudent的父類,而CStudent又是CTeacher的父類,那麼在建立CTeacher對象的時候,首先調用基類也就是CPerson的建構函式,然後按照層級,一層一層下來。ps:2012-4-12
在java中,執行個體化一個子類的對象,首先會調用父類的無參建構函式。如果父類沒有顯式定義建構函式,那麼會調用預設建構函式,這個預設建構函式是由編譯器自動產生的。如果父類顯式定義了建構函式,那麼編譯器就不再為父類產生預設預設建構函式。
假設父類中定義了一個帶參數的建構函式,而沒有定義無參建構函式,這時候執行個體化一個子類的對象,就會出現編譯錯誤,因為子類首先要調用父類的無參建構函式,但是父類沒有顯式定義,編譯器又不為父類產生預設建構函式。這時候可以通過在父類中顯示定義無參建構函式來解決這個錯誤。
this()和super()都可以用來調用建構函式,而this()用於在同一個類內調用其他的建構函式,比如首先在Student類中定義了一個建構函式Student(name,age),又另外定義了一個建構函式Student(name,age,school),那麼在第二個建構函式中可以通過this(name,age)的形式來調用第一個建構函式,注意這裡this(name,age)必須寫在第二個建構函式的首行。而super用於從子類的構造方法中調用父類的構造方法。比如父類Person有建構函式Person(String name, int age),而子類有建構函式Student(String name, int age, String school, String grade),那麼就可以在子類建構函式中通過super(name,age)來調用父類建構函式。
建議:最好為每個類都顯示定義無參建構函式。
執行個體
Person類
View Code
public class Person { private String name = ""; private int age = 0; public Person() { System.out.println("Person類無參數建構函式"); } public Person(String name, int age) { this.name = name; this.age = age; System.out.println("Person類帶2參數的建構函式"); }}
Student類
View Code
public class Student extends Person { private String school; private String grade; public Student() { System.out.println("Student類無參數的建構函式"); } public Student(String name, int age, String school) { super(name,age); this.school=school; System.out.println("Student類帶3參數的建構函式"); } public Student(String name, int age, String school, String grade) { this(name,age,school); this.grade = grade; System.out.println("Student類帶4參數的建構函式"); }}
Test類
View Code
public class Test { public static void main(String[] args) { System.out.println("無參數執行個體:"); Student st1 = new Student(); System.out.println("---------------------------"); System.out.println("3參數執行個體:"); Student st2 = new Student("zhangshan",25,"mit"); System.out.println("---------------------------");// System.out.println("4參數執行個體:"); Student st3 = new Student("lisi", 24, "mit", "研究生"); }}
執行個體運行結果:
無參數執行個體:
Person類無參數建構函式
Student類無參數的建構函式
---------------------------
3參數執行個體:
Person類帶2參數的建構函式
Student類帶3參數的建構函式
---------------------------
4參數執行個體:
Person類帶2參數的建構函式
Student類帶3參數的建構函式
Student類帶4參數的建構函式