繼承關(guān)系的構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行順序?yàn)椋?/p>
成都創(chuàng)新互聯(lián)公司是工信部頒發(fā)資質(zhì)IDC服務(wù)器商,為用戶提供優(yōu)質(zhì)的成都電信服務(wù)器托管服務(wù)
1、父類構(gòu)造函數(shù)執(zhí)行。
2、子類構(gòu)造函數(shù)執(zhí)行。
3、子類析構(gòu)函數(shù)執(zhí)行。
4、父類析構(gòu)函數(shù)執(zhí)行。
組合關(guān)系的構(gòu)造函數(shù)和析構(gòu)函數(shù)執(zhí)行順序?yàn)椋?/p>
1、執(zhí)行類成員對象的構(gòu)造函數(shù)。
2、執(zhí)行類自己的構(gòu)造函數(shù)。
3、執(zhí)行類自己的析構(gòu)函數(shù)。
4、執(zhí)行類成員的析構(gòu)函數(shù)。
container有兩個(gè)成員,one,two,所以在執(zhí)行這個(gè)container構(gòu)造函數(shù)之前執(zhí)行object類的構(gòu)造函數(shù)兩次。
擴(kuò)展資料:
把類的聲明放在main函數(shù)之前,它的作用域是全局的。這樣做可以使main函數(shù)更簡練一些。在main函數(shù)中定義了兩個(gè)對象并且給出了初值,然后輸出兩個(gè)學(xué)生的數(shù)據(jù)。
當(dāng)主函數(shù)結(jié)束時(shí)調(diào)用析構(gòu)函數(shù),輸出stud has been destructe!。值得注意的是,真正實(shí)用的析構(gòu)函數(shù)一般是不含有輸出信息的。
在本程序中,成員函數(shù)是在類中定義的,如果成員函數(shù)的數(shù)目很多以及函數(shù)的長度很長,類的聲明就會(huì)占很大的篇幅,不利于閱讀程序。
而且為了隱藏實(shí)現(xiàn),一般是有必要將類的聲明和實(shí)現(xiàn)(具體方法代碼)分開編寫的,這也是一個(gè)良好的編程習(xí)慣。即可以在類的外面定義成員函數(shù),而在類中只用函數(shù)的原型作聲明。
參考資料來源:百度百科-析構(gòu)函數(shù)
構(gòu)造函數(shù)只是起初始化值的作用,但實(shí)例化一個(gè)對象的時(shí)候,可以通過實(shí)例去傳遞參數(shù),從主函數(shù)傳遞到其他的函數(shù)里面,這樣就使其他的函數(shù)里面有值了。
析構(gòu)函數(shù)與構(gòu)造函數(shù)的作用相反,用于撤銷對象的一些特殊任務(wù)處理,可以是釋放對象分配的內(nèi)存空間。
把類的聲明放在main函數(shù)之前,它的作用域是全局的。這樣做可以使main函數(shù)更簡練一些。在main函數(shù)中定義了兩個(gè)對象并且給出了初值,然后輸出兩個(gè)學(xué)生的數(shù)據(jù)。
當(dāng)主函數(shù)結(jié)束時(shí)調(diào)用析構(gòu)函數(shù),輸出stud has been destructe!。值得注意的是,真正實(shí)用的析構(gòu)函數(shù)一般是不含有輸出信息的。
擴(kuò)展資料:
當(dāng)定義一個(gè)類的時(shí)候,通常情況下都會(huì)顯示該類的構(gòu)造函數(shù),并在函數(shù)中指定初始化的工作也可省略,不過Java編譯器會(huì)提供一個(gè)默認(rèn)的構(gòu)造函數(shù).此默認(rèn)構(gòu)造函數(shù)是不帶參數(shù)的。而一般的方法不存在這一特點(diǎn)。
構(gòu)造函數(shù)有回滾的效果,構(gòu)造函數(shù)拋出異常時(shí),構(gòu)造的是一個(gè)不完整對象,會(huì)回滾,將此不完整對象的成員釋放(c++)。
當(dāng)一個(gè)類只定義了私有的構(gòu)造函數(shù),將無法通過new關(guān)鍵字來創(chuàng)建其對象,當(dāng)一個(gè)類沒有定義任何構(gòu)造函數(shù),C#編譯器會(huì)為其自動(dòng)生成一個(gè)默認(rèn)的無參的構(gòu)造函數(shù)。
構(gòu)造函數(shù)是一種用于創(chuàng)建對象的特殊函數(shù),當(dāng)創(chuàng)建對象是,系統(tǒng)自動(dòng)調(diào)用構(gòu)造函數(shù),不能在程序中直接調(diào)用.
構(gòu)造函數(shù)名與類名相同,一個(gè)類可以擁有多個(gè)構(gòu)造函數(shù)(重載),構(gòu)造函數(shù)可以有任意類型的參數(shù),但不能具有返回類型!
構(gòu)造函數(shù)的作用是:為對象分配空間;對數(shù)據(jù)成員賦初值;請求起他資源.
析構(gòu)函數(shù)作用是清除對象,釋放內(nèi)存等
類是編程人員表達(dá)自定義數(shù)據(jù)類型的C++機(jī)制。它和C語言中的結(jié)構(gòu)類似,C++類
支持?jǐn)?shù)據(jù)抽象和面向?qū)ο蟮某绦蛟O(shè)計(jì),從某種意義上說,也就是數(shù)據(jù)類型的設(shè)
計(jì)和實(shí)現(xiàn)。
那么
String
類的原型如下
class
String
{
public:
String(const
char
*str=NULL);
//構(gòu)造函數(shù)
String(const
String
other);
//拷貝構(gòu)造函數(shù)
~String(void);
//析構(gòu)函數(shù)
String
operator=(const
String
other);
//等號操作符重載,賦值函數(shù)
ShowString();
private:
char
*m_data;
//字符指針
};
String::~String()
{
delete
[]
m_data;
//析構(gòu)函數(shù),釋放地址空間
}
String::String(const
char
*str)
{
if
(str==NULL)//當(dāng)初始化串不存在的時(shí)候,為m_data申請一個(gè)空間存放'/0';
{
m_data=new
char[1];
*m_data='/0';
}
else//當(dāng)初始化串存在的時(shí)候,為m_data申請同樣大小的空間存放該串;
{
int
length=strlen(str);
m_data=new
char[length+1];
strcpy(m_data,str);
}
}
String::String(const
String
other)//拷貝構(gòu)造函數(shù),功能與構(gòu)造函數(shù)類似。
{
int
length=strlen(other.m_data);
m_data=new
[length+1];
strcpy(m_data,other.m_data);
}
String
String::operator
=(const
String
other)
//賦值函數(shù)
{
if
(this==other)//當(dāng)?shù)刂废嗤瑫r(shí),直接返回;
return
*this;
delete
[]
m_data;//當(dāng)?shù)刂凡幌嗤瑫r(shí),刪除原來申請的空間,重新開始構(gòu)造;
int
length=sizeof(other.m_data);
m_data=new
[length+1];
strcpy(m_data,other.m_data);
return
*this;
}
String::ShowString()//由于m_data是私有成員,對象只能通過public成員函數(shù)來訪問;
{
coutthis-m_dataendl;
}
測試一下:
main()
{
String
AD;
char
*
p="ABCDE";
String
B(p);
AD.ShowString();
AD=B;
AD.ShowString();
}
摘 要:構(gòu)造函數(shù)與析構(gòu)函數(shù)是一個(gè)類中看似較為簡單的兩類函數(shù),但在實(shí)際運(yùn)用過程中總會(huì)出現(xiàn)一些意想不到的運(yùn)行錯(cuò)誤。本文將較系統(tǒng)的介紹構(gòu)造函數(shù)與析構(gòu)函數(shù)的原理及在C#中的運(yùn)用,以及在使用過程中需要注意的若干事項(xiàng)。
關(guān)鍵字:構(gòu)造函數(shù);析構(gòu)函數(shù);垃圾回收器;非托管資源;托管資源
一.構(gòu)造函數(shù)與析構(gòu)函數(shù)的原理
作為比C更先進(jìn)的語言,C#提供了更好的機(jī)制來增強(qiáng)程序的安全性。C#編譯器具有嚴(yán)格的類型安全檢查功能,它幾乎能找出程序中所有的語法問題,這的確幫了程序員的大忙。但是程序通過了編譯檢查并不表示錯(cuò)誤已經(jīng)不存在了,在“錯(cuò)誤”的大家庭里,“語法錯(cuò)誤”的地位只能算是冰山一角。級別高的錯(cuò)誤通常隱藏得很深,不容易發(fā)現(xiàn)。
根據(jù)經(jīng)驗(yàn),不少難以察覺的程序錯(cuò)誤是由于變量沒有被正確初始化或清除造成的,而初始化和清除工作很容易被人遺忘。微軟利用面向?qū)ο蟮母拍钤谠O(shè)計(jì)C#語言時(shí)充分考慮了這個(gè)問題并很好地予以解決:把對象的初始化工作放在構(gòu)造函數(shù)中,把清除工作放在析構(gòu)函數(shù)中。當(dāng)對象被創(chuàng)建時(shí),構(gòu)造函數(shù)被自動(dòng)執(zhí)行。當(dāng)對象消亡時(shí),析構(gòu)函數(shù)被自動(dòng)執(zhí)行。這樣就不用擔(dān)心忘記對象的初始化和清除工作。
二.構(gòu)造函數(shù)在C#中的運(yùn)用
構(gòu)造函數(shù)的名字不能隨便起,必須讓編譯器認(rèn)得出才可以被自動(dòng)執(zhí)行。它的命名方法既簡單又合理:讓構(gòu)造函數(shù)與類同名。除了名字外,構(gòu)造函數(shù)的另一個(gè)特別之處是沒有返回值類型,這與返回值類型為void的函數(shù)不同。如果它有返回值類型,那么編譯器將不知所措。在你可以訪問一個(gè)類的方法、屬性或任何其它東西之前, 第一條執(zhí)行的語句是包含有相應(yīng)類的構(gòu)造函數(shù)。甚至你自己不寫一個(gè)構(gòu)造函數(shù),也會(huì)有一個(gè)缺省構(gòu)造函數(shù)提供給你。
class TestClass
{
public TestClass(): base() {} // 由CLR提供
}
下面列舉了幾種類型的構(gòu)造函數(shù)
1)缺省構(gòu)造函數(shù)
class TestClass
{
public TestClass(): base() {}
}
上面已介紹,它由系統(tǒng)(CLR)提供。
2)實(shí)例構(gòu)造函數(shù)
實(shí)例構(gòu)造函數(shù)是實(shí)現(xiàn)對類中實(shí)例進(jìn)行初始化的方法成員。如:
using System;
class Point
{
public double x, y;
public Point()
{
this.x = 0;
this.y = 0;
}
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
}
class Test
{
static void Main()
{
Point a = new Point();
Point b = new Point(3, 4); // 用構(gòu)造函數(shù)初始化對象
}
}
聲明了一個(gè)類Point,它提供了兩個(gè)構(gòu)造函數(shù)。它們是重載的。一個(gè)是沒有參數(shù)的Point構(gòu)造函數(shù)和一個(gè)是有兩個(gè)double參數(shù)的Point構(gòu)造函數(shù)。如果類中沒有提供這些構(gòu)造函數(shù),那么會(huì)CLR會(huì)自動(dòng)提供一個(gè)缺省構(gòu)造函數(shù)的。但一旦類中提供了自定義的構(gòu)造函數(shù),如Point()和Point(double x, double y),則缺省構(gòu)造函數(shù)將不會(huì)被提供,這一點(diǎn)要注意。
3) 靜態(tài)構(gòu)造函數(shù)
靜態(tài)構(gòu)造函數(shù)是實(shí)現(xiàn)對一個(gè)類進(jìn)行初始化的方法成員。它一般用于對靜態(tài)數(shù)據(jù)的初始化。靜態(tài)構(gòu)造函數(shù)不能有參數(shù),不能有修飾符而且不能被調(diào)用,當(dāng)類被加載時(shí),類的靜態(tài)構(gòu)造函數(shù)自動(dòng)被調(diào)用。如:
using System.Data;
class Employee
{
private static DataSet ds;
static Employee()
{
ds = new DataSet(...);
}
}
聲明了一個(gè)有靜態(tài)構(gòu)造函數(shù)的類Employee。注意靜態(tài)構(gòu)造函數(shù)只能對靜態(tài)數(shù)據(jù)成員進(jìn)行初始化,而不能對非靜態(tài)數(shù)據(jù)成員進(jìn)行初始化。但是,非靜態(tài)構(gòu)造函數(shù)既可以對靜態(tài)數(shù)據(jù)成員賦值,也可以對非靜態(tài)數(shù)據(jù)成員進(jìn)行初始化。
如果類僅包含靜態(tài)成員,你可以創(chuàng)建一個(gè)private的構(gòu)造函數(shù):private TestClass() {…},但是private意味著從類的外面不可能訪問該構(gòu)造函數(shù)。所以,它不能被調(diào)用,且沒有對象可以被該類定義實(shí)例化。
以上是幾種類型構(gòu)造函數(shù)的簡單運(yùn)用,下面將重點(diǎn)介紹一下在類的層次結(jié)構(gòu)中(即繼承結(jié)構(gòu)中)基類和派生類的構(gòu)造函數(shù)的使用方式。派生類對象的初始化由基類和派生類共同完成:基類的成員由基類的構(gòu)造函數(shù)初始化,派生類的成員由派生類的構(gòu)造函數(shù)初始化。
當(dāng)創(chuàng)建派生類的對象時(shí),系統(tǒng)將會(huì)調(diào)用基類的構(gòu)造函數(shù)和派生類的構(gòu)造函數(shù),構(gòu) 造函數(shù)的執(zhí)行次序是:先執(zhí)行基類的構(gòu)造函數(shù),再執(zhí)行派生類的構(gòu)造函數(shù)。如果派生類又有對象成員,則,先執(zhí)行基類的構(gòu)造函數(shù),再執(zhí)行成員對象類的構(gòu)造函數(shù),最后執(zhí)行派生類的構(gòu)造函數(shù)。
至于執(zhí)行基類的什么構(gòu)造函數(shù),缺省情況下是執(zhí)行基類的無參構(gòu)造函數(shù),如果要執(zhí)行基類的有參構(gòu)造函數(shù),則必須在派生類構(gòu)造函數(shù)的成員初始化表中指出。如:
class A
{ private int x;
public A( ) { x = 0; }
public A( int i ) { x = i; }
};
class B : A
{ private int y;
public B( ) { y = 0; }
public B( int i ) { y = i; }
public B( int i, int j ):A(i) { y = j; }
};
B b1 = new B(); //執(zhí)行基類A的構(gòu)造函數(shù)A(),再執(zhí)行派生類的構(gòu)造函數(shù)B()
B b2 = new B(1); //執(zhí)行基類A的構(gòu)造函數(shù)A(),再執(zhí)行派生類的構(gòu)造函數(shù)B(int)
B b3 = new B(0,1); //執(zhí)行執(zhí)行基類A的構(gòu)造函數(shù)A(int) ,再執(zhí)行派生類的
構(gòu)造函數(shù)B(int,int)
在這里構(gòu)造函數(shù)的執(zhí)行次序是一定要分析清楚的。另外,如果基類A中沒有提供無參構(gòu)造函數(shù)public A( ) { x = 0; },則在派生類的所有構(gòu)造函數(shù)成員初始化表中必須指出基類A的有參構(gòu)造函數(shù)A(i),如下所示:
class A
{ private int x;
public A( int i ) { x = i; }
};
class B : A
{ private int y;
public B():A(i) { y = 0; }
public B(int i):A(i) { y = i; }
public B(int i, int j):A(i) { y = j; }
};
三.析構(gòu)函數(shù)和垃圾回收器在C#中的運(yùn)用
析構(gòu)函數(shù)是實(shí)現(xiàn)銷毀一個(gè)類的實(shí)例的方法成員。析構(gòu)函數(shù)不能有參數(shù),不能任何修飾符而且不能被調(diào)用。由于析構(gòu)函數(shù)的目的與構(gòu)造函數(shù)的相反,就加前綴‘~’以示區(qū)別。
雖然C#(更確切的說是CLR)提供了一種新的內(nèi)存管理機(jī)制---自動(dòng)內(nèi)存管理機(jī)制(Automatic memory management),資源的釋放是可以通過“垃圾回收器” 自動(dòng)完成的,一般不需要用戶干預(yù),但在有些特殊情況下還是需要用到析構(gòu)函數(shù)的,如在C#中非托管資源的釋放。
資源的.釋放一般是通過"垃圾回收器"自動(dòng)完成的,但具體來說,仍有些需要注意的地方:
1. 值類型和引用類型的引用其實(shí)是不需要什么"垃圾回收器"來釋放內(nèi)存的,因?yàn)楫?dāng)它們出了作用域后會(huì)自動(dòng)釋放所占內(nèi)存,因?yàn)樗鼈兌急4嬖跅?Stack)中;
2. 只有引用類型的引用所指向的對象實(shí)例才保存在堆(Heap)中,而堆因?yàn)槭且粋€(gè)自由存儲(chǔ)空間,所以它并沒有像"棧"那樣有生存期("棧"的元素彈出后就代表生存期結(jié)束,也就代表釋放了內(nèi)存),并且要注意的是,"垃圾回收器"只對這塊區(qū)域起作用;
然而,有些情況下,當(dāng)需要釋放非托管資源時(shí),就必須通過寫代碼的方式來解決。通常是使用析構(gòu)函數(shù)釋放非托管資源,將用戶自己編寫的釋放非托管資源的代碼段放在析構(gòu)函數(shù)中即可。需要注意的是,如果一個(gè)類中沒有使用到非托管資源,那么一定不要定義析構(gòu)函數(shù),這是因?yàn)閷ο髨?zhí)行了析構(gòu)函數(shù),那么"垃圾回收器"在釋放托管資源之前要先調(diào)用析構(gòu)函數(shù),然后第二次才真正釋放托管資源,這樣一來,兩次刪除動(dòng)作的花銷比一次大多的。下面使用一段代碼來示析構(gòu)函數(shù)是如何使用的:
public class ResourceHolder
{
~ResourceHolder()
{
// 這里是清理非托管資源的用戶代碼段
}
}
四.小結(jié)
構(gòu)造函數(shù)與析構(gòu)函數(shù)雖然是一個(gè)類中形式上較簡單的函數(shù),但它們的使用決非看上去那么簡單,因此靈活而正確的使用構(gòu)造函數(shù)與析構(gòu)函數(shù)能夠幫你更好的理解CLR的內(nèi)存管理機(jī)制,以及更好的管理系統(tǒng)中的資源。
網(wǎng)頁名稱:c語言構(gòu)造和析構(gòu)函數(shù) c++析構(gòu)函數(shù)和構(gòu)造函數(shù)
文章地址:http://muchs.cn/article12/docoddc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、小程序開發(fā)、全網(wǎng)營銷推廣、App開發(fā)、服務(wù)器托管、網(wǎng)站導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)