第一篇:2.3實(shí)驗(yàn)二、三 構(gòu)造函數(shù)與析構(gòu)函數(shù)
南昌航空大學(xué)實(shí)驗(yàn)報(bào)告
年月日 課程名稱:面向?qū)ο蟪绦蛟O(shè)計(jì)實(shí)驗(yàn)名稱:構(gòu)造函數(shù)與析構(gòu)函數(shù)班級(jí): XXXXXXX學(xué)生姓名:XXXXXX學(xué)號(hào):指導(dǎo)教師評(píng)定:XX簽名:XXXXX1、實(shí)驗(yàn)?zāi)康摹だ斫忸惻c對(duì)象的區(qū)別。
·學(xué)習(xí)掌握定義構(gòu)造函數(shù)與析構(gòu)函數(shù)的方法。
·學(xué)習(xí)把握默認(rèn)構(gòu)造函數(shù)的意義。
·了解類成員初始化,掌握構(gòu)造與析構(gòu)類成員的方式。
2、實(shí)驗(yàn)內(nèi)容
(1)
創(chuàng)建一個(gè)Employee類,該類中用字符數(shù)組存放Employee的信息,如姓名、地址、市、省、及郵政編碼;每個(gè)成員函數(shù)的定義放在類定義之外;成員函數(shù)包括改變姓名數(shù)據(jù)成員等;構(gòu)造函數(shù)完成成員數(shù)據(jù)的初始化;用Display()函數(shù)將完整的對(duì)象數(shù)據(jù)打印出來(lái);其中數(shù)據(jù)成員是保護(hù)的,成員函數(shù)是公共的。
#include
#include
#include
class Employee
{
public:
};Employee(char n[20],char a[50],char s[20],char sh[20],char p[6]);void ChangeName(char ch_name[20]);void Display();char name[20];char address[50];char shi[20];char sheng[20];char post[6];protected:
給出各個(gè)成員函數(shù)的具體實(shí)現(xiàn)
void main()
{
Employee em(“rer r34t3”,“5 West St.”,“Revere”,“CA”,“12290”);em.Display();em.ChangeName(“sdfesfefe”);
}
em.Display();
(2)設(shè)計(jì)一個(gè)表示矩形的類Rect,其矩形成員長(zhǎng)float * Length ,寬float * Width為指針變量,設(shè)計(jì)相應(yīng)成員函數(shù),實(shí)現(xiàn)下列功能:
① 構(gòu)造函數(shù)設(shè)置長(zhǎng)和寬(默認(rèn)為1)。
② 復(fù)制構(gòu)造函數(shù)用老對(duì)象生成新對(duì)象。
③ set()函數(shù)設(shè)置長(zhǎng)和寬(默認(rèn)為0)。
④ 計(jì)算并返回長(zhǎng)方形的周長(zhǎng)。
⑤ 計(jì)算并返回長(zhǎng)方形的面積。
⑥ 析構(gòu)函數(shù)釋放動(dòng)態(tài)分配的長(zhǎng)和寬。
編制主程序應(yīng)用指針建立對(duì)象測(cè)試類。
#include
class Rect{
float *Length,*Width;
public:
Rect(float a=1,float b=1);
Rect(Rect &r);
void set(float a=0,float b=0);
float peri();
float area();
~Rect(){delete Length;delete Width;}
};
補(bǔ)充其余代碼
//主函數(shù)
void main()
{ Rect r1(55.5,40);
cout<<“周長(zhǎng)為:”< cout<<“---------------------n”; Rect *p=new Rect(r1);//思考:此處改為 Rect *p=new Rect;下一行的輸出會(huì)是什么結(jié)果 cout<<“周長(zhǎng)為:”< peri()<<“面積為: ”< area()< p->set(20.5,13); cout<<“周長(zhǎng)為:”< peri()<<“面積為: ”< area()< } 類是編程人員表達(dá)自定義數(shù)據(jù)類型的C++機(jī)制。它和C語(yǔ)言中的結(jié)構(gòu)類似,C++類支持?jǐn)?shù)據(jù)抽象和面向?qū)ο蟮某绦蛟O(shè)計(jì),從某種意義上說(shuō),也就是數(shù)據(jù)類型的設(shè)計(jì)和實(shí)現(xiàn)。 一、類的設(shè)計(jì) 1.類的聲明 class 類名 { private://私有 ...public://公有 ...}; 2.類的成員 一般在C++類中,所有定義的變量和函數(shù)都是類的成員。如果是變量,我們就叫它數(shù)據(jù)成員如果是函數(shù),我們就叫它成員函數(shù)。 3.類成員的可見(jiàn)性 private和public訪問(wèn)控制符決定了成員的可見(jiàn)性。由一個(gè)訪問(wèn)控制符設(shè)定的可訪問(wèn)狀態(tài)將一直持續(xù)到下一個(gè)訪問(wèn)控制符出現(xiàn),或者類聲明的結(jié)束。私有成員僅能被同一個(gè)類中的成員函數(shù)訪問(wèn),公有成員既可以被同一類中的成員函數(shù)訪問(wèn),也可以被其他已經(jīng)實(shí)例化的類中函數(shù)訪問(wèn)。當(dāng)然,這也有例外的情況,這是以后要討論的友元函數(shù)。類中默認(rèn)的數(shù)據(jù)類型是private,結(jié)構(gòu)中的默認(rèn)類型是public。一般情況下,變量都作為私有成員出現(xiàn),函數(shù)都作為公有成員出現(xiàn)。 類中還有一種訪問(wèn)控制符protected,叫保護(hù)成員,以后再說(shuō)明。 4.初始化 在聲明一個(gè)類的對(duì)象時(shí),可以用圓括號(hào)()包含一個(gè)初始化表。 看下面一個(gè)例子: #include “iostream.h” class Box { private: int height,width,depth;//3個(gè)私有數(shù)據(jù)成員 public: Box(int,int,int); ~Box(); int volume();//成員函數(shù) }; Box::Box(int ht,int wd,int dp) { height=ht; width=wd; depth=dp; } Box::~Box() { //nothing } int Box::volume() { return height*width*depth; } int main() { Box thisbox(3,4,5);//聲明一個(gè)類對(duì)象并初始化 cout< return 0; } 當(dāng)一個(gè)類中沒(méi)有private成員和protected成員時(shí),也沒(méi)有虛函數(shù),并且不是從其他類中派生出來(lái)的,可以用{}來(lái)初始化。(以后再講解) 5.內(nèi)聯(lián)函數(shù) 內(nèi)聯(lián)函數(shù)和普通函數(shù)的區(qū)別是:內(nèi)聯(lián)函數(shù)是在編譯過(guò)程中展開(kāi)的。通常內(nèi)聯(lián)函數(shù)必須簡(jiǎn)短。定義類的內(nèi)聯(lián)函數(shù)有兩種方法:一種和C語(yǔ)言一樣,在定義函數(shù)時(shí)使用關(guān)鍵字inline。如: inline int Box::volume() { return height*width*depth; } 還有一種方法就是直接在類聲明的內(nèi)部定義函數(shù)體,而不是僅僅給出一個(gè)函數(shù)原型。我們把上面的函數(shù)簡(jiǎn)化一下: #include “iostream.h” class Box { private: int height,width,depth; public: Box(int ht,int wd,int dp) { height=ht; width=wd; depth=dp; } ~Box(); int volume() { return height*width*depth; } }; int main() { Box thisbox(3,4,5);//聲明一個(gè)類對(duì)象并初始化 cout< return 0; } 這樣,兩個(gè)函數(shù)都默認(rèn)為內(nèi)聯(lián)函數(shù)了。 二、構(gòu)造函數(shù) 什么是構(gòu)造函數(shù)?通俗的講,在類中,函數(shù)名和類名相同的函數(shù)稱為構(gòu)造函數(shù)。上面的Box()函數(shù)就是構(gòu)造函數(shù)。C++允許同名函數(shù),也就允許在一個(gè)類中有多個(gè)構(gòu)造函數(shù)。如果一個(gè)都沒(méi)有,編譯器將為該類產(chǎn)生一個(gè)默認(rèn)的構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)可能會(huì)完成一些工作,也可能什么都不做。 絕對(duì)不能指定構(gòu)造函數(shù)的類型,即使是void型都不可以。實(shí)際上構(gòu)造函數(shù)默認(rèn)為void型。 當(dāng)一個(gè)類的對(duì)象進(jìn)入作用域時(shí),系統(tǒng)會(huì)為其數(shù)據(jù)成員分配足夠的內(nèi)存,但是系統(tǒng)不一定將其初始化。和內(nèi)部數(shù)據(jù)類型對(duì)象一樣,外部對(duì)象的數(shù)據(jù)成員總是初始化為0。局部對(duì)象不會(huì)被初始化。構(gòu)造函數(shù)就是被用來(lái)進(jìn)行初始化工作的。當(dāng)自動(dòng)類型的類對(duì)象離開(kāi)其作用域時(shí),所站用的內(nèi)存將釋放回系統(tǒng)。 看上面的例子,構(gòu)造函數(shù)Box()函數(shù)接受三個(gè)整型擦黑素,并把他們賦值給立方體對(duì)象的數(shù)據(jù)成員。 如果構(gòu)造函數(shù)沒(méi)有參數(shù),那么聲明對(duì)象時(shí)也不需要括號(hào)。 1.使用默認(rèn)參數(shù)的構(gòu)造函數(shù) 當(dāng)在聲明類對(duì)象時(shí),如果沒(méi)有指定參數(shù),則使用默認(rèn)參數(shù)來(lái)初始化對(duì)象。 #include “iostream.h” class Box { private: int height,width,depth; public: Box(int ht=2,int wd=3,int dp=4) { height=ht; width=wd; depth=dp; } ~Box(); int volume() { return height*width*depth; } }; int main() { Box thisbox(3,4,5);//初始化 Box defaulbox;//使用默認(rèn)參數(shù) cout< cout< 4return 0; } 2.默認(rèn)構(gòu)造函數(shù) 沒(méi)有參數(shù)或者參數(shù)都是默認(rèn)值的構(gòu)造函數(shù)稱為默認(rèn)構(gòu)造函數(shù)。如果你不提供構(gòu)造函數(shù),編譯器會(huì)自動(dòng)產(chǎn)生一個(gè)公共的默認(rèn)構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)什么都不做。如果至少提供一個(gè)構(gòu)造函數(shù),則編譯器就不會(huì)產(chǎn)生默認(rèn)構(gòu)造函數(shù)。 3.重載構(gòu)造函數(shù) 一個(gè)類中可以有多個(gè)構(gòu)造函數(shù)。這些構(gòu)造函數(shù)必須具有不同的參數(shù)表。在一個(gè)類中需要接受不同初始化值時(shí),就需要編寫(xiě)多個(gè)構(gòu)造函數(shù),但有時(shí)候只需要一個(gè)不帶初始值的空的Box對(duì)象。 #include “iostream.h” class Box { private: int height,width,depth; public: Box(){ //nothing } Box(int ht=2,int wd=3,int dp=4) { height=ht; width=wd; depth=dp; } ~Box(); int volume() { return height*width*depth; } }; int main() { Box thisbox(3,4,5);//初始化 Box otherbox; otherbox=thisbox; cout< return 0; } 這兩個(gè)構(gòu)造函數(shù)一個(gè)沒(méi)有初始化值,一個(gè)有。當(dāng)沒(méi)有初始化值時(shí),程序使用默認(rèn)值,即2,3,4。 但是這樣的程序是不好的。它允許使用初始化過(guò)的和沒(méi)有初始化過(guò)的Box對(duì)象,但它沒(méi)有考慮當(dāng)thisbox給otherbox賦值失敗后,volume()該返回什么。較好的方法是,沒(méi)有參數(shù)表的構(gòu)造函數(shù)也把默認(rèn)值賦值給對(duì)象。 class Box { int height,width,depth; public: Box() { height=0;width=0;depth=0; } Box(int ht,int wd,int dp) { height=ht;width=wd;depth=dp; } int volume() { return height*width*depth; } }; 這還不是最好的方法,更好的方法是使用默認(rèn)參數(shù),根本不需要不帶參數(shù)的構(gòu)造函數(shù)。 class Box { int height,width,depth; public: Box(int ht=0,int wd=0,int dp=0) { height=ht;width=wd;depth=dp; } int volume() { return height*width*depth; } }; 三、析構(gòu)函數(shù) 當(dāng)一個(gè)類的對(duì)象離開(kāi)作用域時(shí),析構(gòu)函數(shù)將被調(diào)用(系統(tǒng)自動(dòng)調(diào)用)。析構(gòu)函數(shù)的名字和類名一樣,不過(guò)要在前面加上 ~。對(duì)一個(gè)類來(lái)說(shuō),只能允許一個(gè)析構(gòu)函數(shù),析構(gòu)函數(shù)不能有參數(shù),并且也沒(méi)有返回值。析構(gòu)函數(shù)的作用是完成一個(gè)清理工作,如釋放從堆中分配的內(nèi)存。 我們也可以只給出析構(gòu)函數(shù)的形式,而不給出起具體函數(shù)體,其效果是一樣的,如上面的例子。但在有些情況下,析構(gòu)函數(shù)又是必需的。如在類中從堆中分配了內(nèi)存,則必須在析構(gòu)函數(shù)中釋放 關(guān)于構(gòu)造函數(shù)與析構(gòu)函數(shù)的說(shuō)明 ? 構(gòu)造函數(shù)、析構(gòu)函數(shù)一定有。 ? 子類構(gòu)造函數(shù)(開(kāi)始時(shí))一定會(huì)調(diào)用父類構(gòu)造函數(shù)。? 子類析構(gòu)函數(shù)(結(jié)束時(shí))一定會(huì)調(diào)用父類析構(gòu)函數(shù)。 1.如果沒(méi)有定義構(gòu)造函數(shù),C++會(huì)自動(dòng)添加默認(rèn)構(gòu)造函數(shù)(即無(wú)參的構(gòu)造函數(shù),只負(fù)責(zé)分配空間,不負(fù)責(zé)數(shù)據(jù)的初始化值)。 2.如果有定義的構(gòu)造函數(shù)(不管有參的還是無(wú)參的),C++不會(huì)再自動(dòng)添加默認(rèn)構(gòu)造函數(shù)。 3.子類的構(gòu)造函數(shù)一定會(huì)調(diào)用父類構(gòu)造函數(shù),在不指定的情況下,自動(dòng)調(diào)用無(wú)參的構(gòu)造函數(shù)。 4.如果沒(méi)有定義析構(gòu)函數(shù),C++會(huì)自動(dòng)添加默認(rèn)析構(gòu)函數(shù)。 5.子類析構(gòu)函數(shù)結(jié)束時(shí)會(huì)自動(dòng)調(diào)用父類析構(gòu)函數(shù)。 類的構(gòu)造函數(shù) 析構(gòu)函數(shù)與賦值函數(shù) 構(gòu)造函數(shù) 析構(gòu)函數(shù)與賦值函數(shù)是每個(gè)類最基本的函數(shù)。它們太普通以致讓人容易麻痹大意,其實(shí)這些貌似簡(jiǎn)單的函數(shù)就象沒(méi)有頂蓋的下水道那樣危險(xiǎn)。 每個(gè)類只有一個(gè)析構(gòu)函數(shù)和一個(gè)賦值函數(shù),但可以有多個(gè)構(gòu)造函數(shù)(包含一個(gè)拷貝構(gòu)造函數(shù),其它的稱為普通構(gòu)造函數(shù))。對(duì)于任意一個(gè)類A,如果不想編寫(xiě)上述函數(shù),C++編譯器將自動(dòng)為A產(chǎn)生四個(gè)缺省的函數(shù),如 A(void);// 缺省的無(wú)參數(shù)構(gòu)造函數(shù) A(const A &a);// 缺省的拷貝構(gòu)造函數(shù) ~A(void);// 缺省的析構(gòu)函數(shù) A & operate =(const A &a);// 缺省的賦值函數(shù) 這不禁讓人疑惑,既然能自動(dòng)生成函數(shù),為什么還要程序員編寫(xiě)? 原因如下: (1)如果使用“缺省的無(wú)參數(shù)構(gòu)造函數(shù)”和“缺省的析構(gòu)函數(shù)”,等于放棄了自主“初始化”和“清除”的機(jī)會(huì),C++發(fā)明人Stroustrup的好心好意白費(fèi)了。 (2)“缺省的拷貝構(gòu)造函數(shù)”和“缺省的賦值函數(shù)”均采用“位拷貝”而非“值拷貝”的方式來(lái)實(shí)現(xiàn),倘若類中含有指針變量,這兩個(gè)函數(shù)注定將出錯(cuò)。 對(duì)于那些沒(méi)有吃夠苦頭的C++程序員,如果他說(shuō)編寫(xiě)構(gòu)造函數(shù) 析構(gòu)函數(shù)與賦值函數(shù)很容易,可以不用動(dòng)腦筋,表明他的認(rèn)識(shí)還比較膚淺,水平有待于提高。 本章以類String的設(shè)計(jì)與實(shí)現(xiàn)為例,深入闡述被很多教科書(shū)忽視了的道理。String的結(jié)構(gòu)如下: class String { public: String(const char *str = NULL);// 普通構(gòu)造函數(shù) String(const String &other);// 拷貝構(gòu)造函數(shù) ~ String(void);// 析構(gòu)函數(shù) String & operate =(const String &other);// 賦值函數(shù)private: char*m_data;// 用于保存字符串 }; C++繼承中構(gòu)造函數(shù)、析構(gòu)函數(shù)調(diào)用順序及虛函數(shù)的動(dòng)態(tài)綁定 昨天面試被問(wèn)到這些,慚愧的很,居然搞混了,悔恨了一把。決定要徹底搞清楚。也算是有所收獲。 首先說(shuō)說(shuō)構(gòu)造函數(shù),大家都知道構(gòu)造函數(shù)里就可以調(diào)用成員變量,而繼承中子類是把基類的成員變成自己的成員,那么也就是說(shuō)子類在構(gòu)造函數(shù)里就可以調(diào)用基類的成員了,這就說(shuō)明創(chuàng)建子類的時(shí)候必須先調(diào)用基類的構(gòu)造函數(shù),只有這樣子類才能在構(gòu)造函數(shù)里使用基類的成員,所以是創(chuàng)建子類時(shí)先調(diào)用基類的構(gòu)造函數(shù)然后再調(diào)用自己的構(gòu)造函數(shù)。通俗點(diǎn)說(shuō),你要用某些物品,但這些物品你沒(méi)辦法自己生產(chǎn),自然就要等別人生產(chǎn)出來(lái),你才能拿來(lái)用。 接著就是析構(gòu)函數(shù)了,上面說(shuō)到子類是將基類的成員變成自己的成員,那么基類就會(huì)只存在子類中直到子類調(diào)用析構(gòu)函數(shù)后。做個(gè)假設(shè):假如在基類的析構(gòu)函數(shù)調(diào)用比子類的先,這樣會(huì)發(fā)生什么事呢?類成員終止了,而類本身卻還在,但是在類存在的情況下,類成員就應(yīng)該還存在的,這不就產(chǎn)生矛盾了嗎?所以子類是調(diào)用自身的析構(gòu)函數(shù)再調(diào)用基類的析構(gòu)函數(shù)。 現(xiàn)在到了虛函數(shù)了,virtual主要作用是在多態(tài)方面,而C++的多態(tài)最主要的是類的動(dòng)態(tài)綁定,動(dòng)態(tài)綁定則是指將子類的指針或引用轉(zhuǎn)換成基類對(duì)象,基類對(duì)象就可以動(dòng)態(tài)判斷調(diào)用哪個(gè)子類成員函數(shù)。這就說(shuō)明在沒(méi)有子類指針或引用轉(zhuǎn)換為基類對(duì)象的話,virtual沒(méi)有存在意義(純虛函數(shù)除外),也就是有沒(méi)有virtual都是調(diào)用其自身的成員函數(shù)。通過(guò)這些分析,對(duì)于virtual就有了眉目了。當(dāng)子類指針或引用轉(zhuǎn)換為基類時(shí),若基類中有用virtual定義的函數(shù),被子類重寫(xiě)后,此基類對(duì)象就會(huì)根據(jù)子類調(diào)用子類中的重寫(xiě)后的函數(shù),而不是基類中的函數(shù);反之,若是基類中沒(méi)有用virtual定義,則不管基類被賦值的是哪個(gè)子類的值,調(diào)用的都是基類的成員函數(shù)(當(dāng)然指的是子類重載的基類函數(shù),不然就算要調(diào)用子類特有的成員函數(shù)也會(huì)編譯不過(guò))。第二篇:二、類的設(shè)計(jì),構(gòu)造函數(shù)和析構(gòu)函數(shù)
第三篇:關(guān)于C++構(gòu)造函數(shù)與析構(gòu)函數(shù)的說(shuō)明
第四篇:類的構(gòu)造函數(shù) 析構(gòu)函數(shù)與賦值函數(shù)
第五篇:構(gòu)造函數(shù)-析構(gòu)函數(shù)的調(diào)用順序