《面向?qū)ο蟪绦蛟O(shè)計(jì)C++》課件1第3章 類和對(duì)象_第1頁
《面向?qū)ο蟪绦蛟O(shè)計(jì)C++》課件1第3章 類和對(duì)象_第2頁
《面向?qū)ο蟪绦蛟O(shè)計(jì)C++》課件1第3章 類和對(duì)象_第3頁
《面向?qū)ο蟪绦蛟O(shè)計(jì)C++》課件1第3章 類和對(duì)象_第4頁
《面向?qū)ο蟪绦蛟O(shè)計(jì)C++》課件1第3章 類和對(duì)象_第5頁
已閱讀5頁,還剩146頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

2023/11/121第3章類和對(duì)象本章學(xué)習(xí)要點(diǎn)類和對(duì)象的概念及其關(guān)系類的聲明和對(duì)象的定義及使用構(gòu)造函數(shù)與析構(gòu)函數(shù)的作用及使用對(duì)象數(shù)組√對(duì)象與指針√對(duì)象與const對(duì)象的動(dòng)態(tài)創(chuàng)建和釋放對(duì)象的復(fù)制和賦值√對(duì)象的移動(dòng)向函數(shù)傳遞對(duì)象字面值常量類圖書館圖書借閱管理系統(tǒng)中類的聲明和對(duì)象的定義2023/11/122第3章類和對(duì)象本章學(xué)習(xí)目標(biāo)正確理解類、對(duì)象及封裝的概念熟練掌握類的聲明和對(duì)象的定義及使用理解構(gòu)造函數(shù)與析構(gòu)函數(shù)的作用及使用掌握對(duì)象與指針及const的特點(diǎn)及使用理解并掌握對(duì)象的復(fù)制和賦值,對(duì)象的移動(dòng)掌握對(duì)象的動(dòng)態(tài)創(chuàng)建和釋放理解對(duì)象作為函數(shù)的參數(shù)傳遞的實(shí)質(zhì)掌握基本的基于對(duì)象的程序設(shè)計(jì)與實(shí)現(xiàn)2023/11/123§3.1類的聲明和對(duì)象的定義本節(jié)主要是關(guān)于類和對(duì)象的概念、類的聲明格式、對(duì)象的定義方法2023/11/1243.1.1類和對(duì)象的概念及關(guān)系對(duì)象封裝了數(shù)據(jù)及在這些數(shù)據(jù)之上的操作的封裝體類對(duì)具有相同屬性和操作的一組對(duì)象的抽象描述類和對(duì)象的關(guān)系類是對(duì)象的抽象;對(duì)象是對(duì)類的實(shí)例化2023/11/125類和對(duì)象的關(guān)系3.1.1類和對(duì)象的概念及關(guān)系2023/11/1263.1.2

類的聲明class類名{public:

公用成員…protected:

受保護(hù)成員…private:

私有成員…};聲明類的一般形式:聲明類的關(guān)鍵字合法標(biāo)識(shí)符公用成員限定符受保護(hù)成員限定符私有成員限定符類結(jié)束要加分號(hào)2023/11/1273.1.2

類的聲明【例3-1】聲明一個(gè)學(xué)生類,要求包括學(xué)生的學(xué)號(hào)、姓名、性別等信息,并且能夠顯示學(xué)生的信息。2023/11/1283.1.2

類的聲明classStudent

//聲明學(xué)生類Student{public: //以下部分為公用成員函數(shù)

voidsetInfo(){cout<<"Pleaseenterstudent’sNo,name,sex,age:"; cin>>stuNo>>stuName>>stuSex>>stuAge;}voidshow(){ cout<<"No.:"<<stuNo<<endl; cout<<"Name:"<<stuName<<endl; cout<<"Sex:"<<stuSex<<endl; cout<<"Age:"<<stuAge<<endl;}private: //以下部分為學(xué)生類Student的私有數(shù)據(jù)成員 stringstuNo; //學(xué)號(hào)stringstuName; //姓名 stringstuSex="男"; //性別intstuAge=0; //年齡};//類聲明結(jié)束,此處必須有分號(hào)2023/11/1293.1.2

類的聲明1.類的成員分為數(shù)據(jù)成員和成員函數(shù)2.成員的可訪問性可分為三類:私有的(private)、受保護(hù)的(protected)、公用的(public)3.由訪問限定符限定它后面的成員的訪問屬性,直到出現(xiàn)下一個(gè)訪問限定符或者類的結(jié)束為止4.在聲明類時(shí),這三種訪問屬性的成員的聲明次序是任意的,并且在一個(gè)類的聲明中不一定這三種訪問屬性全部都出現(xiàn),可能只出現(xiàn)兩種或一種。5.某個(gè)成員訪問限定符在一個(gè)類的聲明中也可以出現(xiàn)多次。注意2023/11/12103.1.3

對(duì)象的定義聲明類之后,再定義對(duì)象如:Studentzhang,wang;或:class

Studentzhang,wang;在聲明類的同時(shí)定義對(duì)象如:class

Student{…}zhang,wang;不出現(xiàn)類名,直接定義對(duì)象如:class{…}zhang,wang;聲明類時(shí)系統(tǒng)并不分配內(nèi)存單元,而定義對(duì)象時(shí)系統(tǒng)會(huì)給每個(gè)對(duì)象分配內(nèi)存單元2023/11/12113.2.1成員函數(shù)的性質(zhì)不屬于任何類的函數(shù)稱為普通函數(shù)。成員函數(shù)隸屬于某個(gè)類成員函數(shù)與普通函數(shù)的區(qū)別成員函數(shù)是屬于某個(gè)類的,是類的一個(gè)成員成員函數(shù)可以指定訪問屬性成員函數(shù)可以訪問本類的任何成員,而普通函數(shù)只能訪問對(duì)象的公用成員對(duì)于成員函數(shù),一般是將需要被類外調(diào)用的聲明為公用的,不需要被類外調(diào)用的聲明為私有的。

2023/11/1212【例3-4】將Student類的成員函數(shù)改為在類外定義的形式。3.2.2在類外定義成員函數(shù)2023/11/1213classStudent

//聲明Student類類型{public: //以下部分為公用成員函數(shù)

voidsetInfo();voidshow();private: //以下部分是私有數(shù)據(jù)成員

intstuNo;//學(xué)號(hào)

charstuName[20];//姓名

stringstuSex="男"; //性別

intstuAge=0; //年齡};

//類聲明結(jié)束//在類的聲明之外定義成員函數(shù)

//在類的聲明之外定義學(xué)生類Student的setInfo成員函數(shù)voidStudent::setInfo(){cout<<"Pleaseenterstudent’sNo,Name,Sex,Age:";cin>>stuNo>>stuName>>stuSex>>stuAge;}2023/11/1214classStudent

//聲明Student類類型{public: //以下部分為公用成員函數(shù)

voidsetInfo();voidshow();private: //以下部分是私有數(shù)據(jù)成員

intstuNo;//學(xué)號(hào)

charstuName[20];//姓名

stringstuSex="男"; //性別

intstuAge=0; //年齡};

//類聲明結(jié)束//在類的聲明之外定義成員函數(shù)

voidStudent::show(){

cout<<"No.:"<<stuNo<<endl;

cout<<"Name:"<<stuName<<endl;

cout<<"Sex:"<<stuSex<<endl;cout<<"Age:"<<stuAge<<endl;}2023/11/12153.2.2在類外定義成員函數(shù)(1)成員函數(shù)在類內(nèi)定義或是在類外定義,對(duì)程序執(zhí)行的效果基本一樣。(2)在類外定義成員函數(shù)時(shí),必須首先在類內(nèi)寫出成員函數(shù)的原型,然后再在類外定義。(3)如果在類外有函數(shù)定義,但是在函數(shù)名前沒有類名和作用域運(yùn)算符進(jìn)行限定,則該函數(shù)被認(rèn)為是普通函數(shù)。(4)如成員函數(shù)的函數(shù)體很短,也可以將其定義在類內(nèi)。(5)在類內(nèi)聲明成員函數(shù),在類外定義成員函數(shù),是軟件工程中要求的良好的編程風(fēng)格。注意2023/11/12163.2.3inline成員函數(shù)inline函數(shù)在編譯時(shí)將被調(diào)用函數(shù)的代碼直接嵌入到調(diào)用函數(shù)處inline成員函數(shù)就是將類中的成員函數(shù)聲明為內(nèi)置的當(dāng)類中的成員函數(shù)是在類內(nèi)定義時(shí),默認(rèn)該成員函數(shù)是inline成員函數(shù)如果成員函數(shù)定義在類的外部,則在成員函數(shù)聲明或定義前必須要有inline關(guān)鍵字2023/11/12173.2.4成員函數(shù)的存儲(chǔ)方式實(shí)例化對(duì)象時(shí)需要分配內(nèi)存空間,數(shù)據(jù)和函數(shù)都需要存儲(chǔ)空間同一個(gè)類的不同對(duì)象的數(shù)據(jù)是不一樣的,因此要為每個(gè)對(duì)象的數(shù)據(jù)成員分配內(nèi)存單元同一個(gè)類的不同對(duì)象的函數(shù)是一樣的,因此將同類的所有對(duì)象的函數(shù)放在一個(gè)公共的區(qū)域。2023/11/12183.2.4成員函數(shù)的存儲(chǔ)方式【例3-5】類的對(duì)象占用內(nèi)存空間實(shí)驗(yàn)。#include<iostream>usingnamespacestd;classTest{public: voidshow(){cout<<"charinTestis:"<<c<<endl;}private: charc;};intmain(){Testtest;cout<<"SizeofTestis"<<sizeof(test)<<endl;return0;}2023/11/12193.2.4成員函數(shù)的存儲(chǔ)方式【例3-6】相同類的不同對(duì)象執(zhí)行相同成員函數(shù)輸出不同結(jié)果。#include<iostream>usingnamespacestd;classTest{public: voidset(charch){c=ch;} voidshow() {cout<<"charinTestis:"<<c<<endl;}private: charc;};intmain(){Testtest1,test2;test1.set('a');test2.set('b');test1.show();test2.show();return0;}2023/11/12203.2.4成員函數(shù)的存儲(chǔ)方式classTest{public: voidset(Test*this,charch){this->c=ch;} voidshow(Test

*this

) {cout<<"charinTestis:"<<this->c<<endl;}private: charc;};intmain(){Testtest1,test2;test1.set(&test1,'a');test2.set(&test2,'b');test1.show(&test1

);test2.show(&test2

);return0;}2023/11/12213.3對(duì)象成員的訪問訪問對(duì)象的成員主要有3種方法通過對(duì)象名和成員運(yùn)算符訪問對(duì)象中的成員通過指向?qū)ο蟮闹羔樤L問對(duì)象中的成員通過對(duì)象的引用訪問對(duì)象中的成員2023/11/12223.3.1成員運(yùn)算符訪問成員通過對(duì)象名和成員運(yùn)算符訪問對(duì)象中的成員的一般形式:

對(duì)象名.成員名在使用對(duì)象的成員時(shí)一定要寫清楚成員所屬的對(duì)象,如果只寫成員名則系統(tǒng)會(huì)誤認(rèn)為是一個(gè)普通的變量或函數(shù)如:在【例3-6】中main函數(shù)里的語句:

test1.show();2023/11/12233.3.2通過指針訪問成員通過指向?qū)ο蟮闹羔樤L問對(duì)象中的成員可以通過C++的“->”運(yùn)算符方便直觀的進(jìn)行,“->”稱為指向運(yùn)算符。例如:

Testtest1;test1.set('a');Test*pTest=&test1;

test1.show();pTest->show();此處兩個(gè)語句的執(zhí)行結(jié)果完全相同,只是采用了不同的訪問對(duì)象成員的形式而已。2023/11/12243.3.3通過引用訪問成員對(duì)象的引用和普通變量的引用在本質(zhì)上是一樣的通過對(duì)象的引用訪問對(duì)象成員和通過對(duì)象訪問成員形式上是一樣的例如:

Testtest1;test1.set('a');Test&refTest=test1;

test1.show();

refTest.show();此處兩個(gè)語句的執(zhí)行結(jié)果完全相同,只是采用了不同的訪問對(duì)象成員的形式而已。classStudent

//聲明Student類類型{public: //以下部分為公用成員函數(shù)

voidsetInfo();voidshow();private: //以下部分是私有數(shù)據(jù)成員

intstuNo;//學(xué)號(hào)

charstuName[20];//姓名

stringstuSex="男"; //性別

intstuAge=0; //年齡};

//類聲明結(jié)束//在類的聲明之外定義成員函數(shù)

voidStudent::show(){

cout<<"No.:"<<stuNo<<endl;

cout<<"Name:"<<stuName<<endl;

cout<<"Sex:"<<stuSex<<endl;cout<<"Age:"<<stuAge<<endl;}2023/11/1225intmain(){

Student

stud;

stud.show();return0;}2023/11/1226classStudent

//聲明Student類類型{public: //以下部分為公用成員函數(shù)

voidsetInfo();

voidshow();private: //以下部分是私有數(shù)據(jù)成員

intstuNo;//學(xué)號(hào)

charstuName[20];//姓名

stringstuSex="男"; //性別

intstuAge=0; //年齡};

//類聲明結(jié)束//在類的聲明之外定義成員函數(shù)

voidStudent::Show(){

cout<<"No.:"<<stuNo<<endl;

cout<<"Name:"<<stuName<<endl;

cout<<"Sex:"<<stuSex<<endl;}voidStudent::setInfo(){

cout<<"Pleaseenterstudent’sNo,Name,Sex,Age:";cin>>stuNo>>stuName>>stuSex>>stuAge;}intmain(){

Student

stud;

stud.setInfo();

stud.show();return0;}2023/11/12273.4.1構(gòu)造函數(shù)1、構(gòu)造函數(shù)的任務(wù)

創(chuàng)建對(duì)象時(shí)對(duì)對(duì)象的數(shù)據(jù)成員初始化【例3-9】構(gòu)造函數(shù)舉例2023/11/1228classSalesData

//聲明圖書交易記錄類SalesData{public:

//定義SalesData類的構(gòu)造函數(shù),構(gòu)造函數(shù)名與類名相同

SalesData(){//利用構(gòu)造函數(shù)對(duì)數(shù)據(jù)成員賦初值bookNo="null";unitsSold=0;revenue=0.0;cout<<"SalesData'sconstructorisexecuted!"<<endl;}……private:stringbookNo;//書號(hào)intunitsSold;//銷售出的冊(cè)數(shù)doublerevenue;//總銷售金額};

//類聲明結(jié)束2023/11/12293.4.1構(gòu)造函數(shù)構(gòu)造函數(shù)的特點(diǎn)(1)構(gòu)造函數(shù)是類的一個(gè)特殊的成員函數(shù),構(gòu)造函數(shù)名與類名相同,且沒有返回值(2)構(gòu)造函數(shù)可以被重載,一個(gè)類可以包含多個(gè)構(gòu)造函數(shù),不同的構(gòu)造函數(shù)之間在形參數(shù)量或形參類型上有所不同。稍后介紹。(3)構(gòu)造函數(shù)不需要用戶調(diào)用,由系統(tǒng)在創(chuàng)建對(duì)象時(shí)自動(dòng)調(diào)用的(4)構(gòu)造函數(shù)不能聲明為const的。(5)構(gòu)造函數(shù)內(nèi)容一般是初始化數(shù)據(jù)語句,但也可以是其他的語句(6)創(chuàng)建對(duì)象時(shí)肯定會(huì)執(zhí)行一個(gè)構(gòu)造函數(shù)2023/11/12303.4.1構(gòu)造函數(shù)默認(rèn)構(gòu)造函數(shù)

如果用戶自己沒有定義構(gòu)造函數(shù),編譯器會(huì)隱式地提供一個(gè)構(gòu)造函數(shù),稱之為合成的默認(rèn)構(gòu)造函數(shù),該構(gòu)造函數(shù)的形參表和函數(shù)體皆為空,它按如下規(guī)則初始化類的數(shù)據(jù)成員:如果存在類內(nèi)的初始值,用它來初始化成員,這是C++11標(biāo)準(zhǔn)中新增的類內(nèi)初始化。否則,默認(rèn)初始化該成員,其初始化規(guī)則與普通變量的默認(rèn)初始化規(guī)則相同。2023/11/12313.4.1構(gòu)造函數(shù)默認(rèn)構(gòu)造函數(shù)

合成的默認(rèn)構(gòu)造函數(shù)只適合非常簡單的類,對(duì)于大多數(shù)普通的類來說,必須定義它自己的默認(rèn)構(gòu)造函數(shù)(該構(gòu)造函數(shù)或者形參表為空,如例3-9中的構(gòu)造函數(shù),或者形參不為空但全部參數(shù)都有默認(rèn)實(shí)參)。2023/11/12323.4.1構(gòu)造函數(shù)2、定義自己的構(gòu)造函數(shù)

classSalesData

//聲明圖書交易記錄類SalesData{public:

SalesData()=default;//無參的默認(rèn)構(gòu)造函數(shù)

//帶1個(gè)conststring&參數(shù)的構(gòu)造函數(shù)

SalesData(conststring&No):bookNo(No){}//帶1個(gè)istream&參數(shù)的構(gòu)造函數(shù)

SalesData(istream&input);//帶3個(gè)參數(shù)(書號(hào)、銷售冊(cè)數(shù)、銷售價(jià)格)的構(gòu)造函數(shù)

SalesData(conststring&No,intn,doubleprice):bookNo(No),unitsSold(n),revenue(n*price){}……};

//類聲明結(jié)束2023/11/12333.4.1構(gòu)造函數(shù)2、定義自己的構(gòu)造函數(shù)

intmain(){SalesDatabook1;book1.show();cout<<endl;

SalesDatabook2("1002"); book2.show();cout<<endl;

SalesDatabook3("1003",2,35.0);book3.show();cout<<endl;……return0;}2023/11/12343.4.1構(gòu)造函數(shù)帶參數(shù)的構(gòu)造函數(shù)一般格式為:構(gòu)造函數(shù)名(參數(shù)表);

實(shí)參是在定義對(duì)象時(shí)給出的,一般格式為:類名對(duì)象名(實(shí)參表);帶參數(shù)的構(gòu)造函數(shù)形式可以方便的實(shí)現(xiàn)對(duì)不同對(duì)象進(jìn)行不同的初始化2023/11/12353.4.1構(gòu)造函數(shù)構(gòu)造函數(shù)重載在類中定義多個(gè)構(gòu)造函數(shù),這些構(gòu)造函數(shù)具有相同的函數(shù)名而參數(shù)表中參數(shù)的個(gè)數(shù)或類型不同相當(dāng)于給類實(shí)例化對(duì)象時(shí)提供了不同的初始化方法2023/11/12363.4.1構(gòu)造函數(shù)(1)如果在類的聲明中沒有寫一個(gè)構(gòu)造函數(shù),系統(tǒng)會(huì)自動(dòng)生成一個(gè)無參的、函數(shù)體為空的默認(rèn)構(gòu)造函數(shù)。默認(rèn)構(gòu)造函數(shù)只是在形式上保證創(chuàng)建對(duì)象時(shí)必須有構(gòu)造函數(shù)。(2)由于一旦寫了一個(gè)構(gòu)造函數(shù),系統(tǒng)就不再提供默認(rèn)的構(gòu)造函數(shù),因此在程序中定義對(duì)象時(shí)一定要注意類中有幾個(gè)構(gòu)造函數(shù),它們要求的參數(shù)分別是什么樣的,如果創(chuàng)建對(duì)象時(shí)給出的參數(shù)表和所有的構(gòu)造函數(shù)的參數(shù)表都不符合,則系統(tǒng)無法創(chuàng)建對(duì)象。(3)使用參數(shù)實(shí)例化對(duì)象時(shí)的格式是:類名對(duì)象名(實(shí)參表);而使用默認(rèn)構(gòu)造函數(shù)實(shí)例化對(duì)象時(shí)的格式是:類名對(duì)象名;注意2023/11/12373、構(gòu)造函數(shù)的初始化列表構(gòu)造函數(shù)的初始化列表為函數(shù)參數(shù)表后面的冒號(hào)及冒號(hào)和花括號(hào)之間的代碼,它負(fù)責(zé)為新創(chuàng)建對(duì)象的一個(gè)或多個(gè)數(shù)據(jù)成員賦初值。它是成員名字的一個(gè)列表,每個(gè)名字后面緊跟括號(hào)括起來的(或者在花括號(hào)內(nèi)的)成員初始值。不同成員的初始化通過逗號(hào)分隔開來。3.4.1構(gòu)造函數(shù)//帶3個(gè)參數(shù)(書號(hào)、銷售冊(cè)數(shù)、銷售價(jià)格)的構(gòu)造函數(shù)SalesData(conststring&No,intn,doubleprice):bookNo(No),unitsSold(n),revenue(n*price){}2023/11/12383、構(gòu)造函數(shù)的初始化列表構(gòu)造函數(shù)的執(zhí)行分為兩個(gè)階段:(1)初始化階段(初始化)初始化階段具體指的是用構(gòu)造函數(shù)初始化列表方式來初始化類中的數(shù)據(jù)成員。沒有在構(gòu)造函數(shù)的初始值列表中顯式地初始化的成員,則該成員將在構(gòu)造函數(shù)體之前執(zhí)行默認(rèn)初始化。(2)普通計(jì)算階段(賦值)執(zhí)行構(gòu)造函數(shù)的函數(shù)體,函數(shù)體內(nèi)一般是對(duì)類的數(shù)據(jù)成員進(jìn)行賦值的操作。這兩個(gè)階段按照順序依次執(zhí)行。3.4.1構(gòu)造函數(shù)2023/11/12393、構(gòu)造函數(shù)的初始化列表初始化列表有時(shí)必不可少除了性能問題之外,有些時(shí)候初始化列表是不可或缺的,以下幾種情況時(shí)必須使用初始化列表:(1)常數(shù)據(jù)成員,因?yàn)槌A恐荒艹跏蓟荒苜x值,所以必須放在初始化列表里面。(2)引用類型成員,引用必須在定義的時(shí)候初始化,并且不能重新賦值,所以也要寫在初始化列表里面。(3)沒有默認(rèn)構(gòu)造函數(shù)的類類型成員,因?yàn)槭褂贸跏蓟斜砜梢圆槐卣{(diào)用默認(rèn)構(gòu)造函數(shù)來初始化,而是直接調(diào)用復(fù)制構(gòu)造函數(shù)初始化(復(fù)制構(gòu)造函數(shù)的內(nèi)容在3.9.1節(jié)介紹)3.4.1構(gòu)造函數(shù)2023/11/12403、構(gòu)造函數(shù)的初始化列表成員初始化的順序:初始化列表中成員初始化按照變量定義的先后順序來初始化,與初始化列表中成員順序無關(guān)。如果成員初始化依賴其他成員的值,那么要注意初始化順序。為了避免這個(gè)問題,一般按照定義的順序來初始化成員。3.4.1構(gòu)造函數(shù)2023/11/12414、委托構(gòu)造函數(shù)委托構(gòu)造函數(shù)是C++11中對(duì)C++的構(gòu)造函數(shù)的一項(xiàng)改進(jìn),其目的是為了簡化構(gòu)造函數(shù)的書寫,減少冗余代碼。一個(gè)委托構(gòu)造函數(shù)可以使用它所屬類的其他構(gòu)造函數(shù)執(zhí)行它自己的初始化過程,或者說它把它自己的一些(或全部)職責(zé)委托給了其他構(gòu)造函數(shù)。3.4.1構(gòu)造函數(shù)2023/11/1242classSalesData

//聲明圖書交易記錄類SalesData{public:

//受委托的構(gòu)造函數(shù),也稱為目標(biāo)構(gòu)造函數(shù)SalesData(conststring&No,intn,doubleprice):bookNo(No),unitsSold(n),revenue(n*price){}

//其余構(gòu)造函數(shù)全部委托給另一個(gè)構(gòu)造函數(shù)SalesData():SalesData("null",0,0){}SalesData(conststring&No):SalesData(No,0,0){}SalesData(istream&input):SalesData(){doubleprice;input>>bookNo>>unitsSold>>price;revenue=unitsSold*price;}

……(此處省略的代碼同例3-10)private:stringbookNo;//書號(hào)intunitsSold;//銷售出的冊(cè)數(shù)doublerevenue;//總銷售金額};2023/11/12431.委托構(gòu)造函數(shù)的初始化列表中有且僅有一個(gè)對(duì)目標(biāo)構(gòu)造函數(shù)的調(diào)用。即,如果委托構(gòu)造函數(shù)的初始化列表中有一個(gè)對(duì)目標(biāo)構(gòu)造函數(shù)的調(diào)用,則該初始化列表中就不能再有其它東西(即不允許再有其它基類或數(shù)據(jù)成員的初始化)。2.目標(biāo)構(gòu)造函數(shù)還可以再委托給另一個(gè)構(gòu)造函數(shù),但不要形成委托環(huán)。如,構(gòu)造函數(shù)C1委托給另一個(gè)構(gòu)造函數(shù)C2,而C2又委托給C1,這樣的代碼通常會(huì)導(dǎo)致編譯錯(cuò)誤。注意2023/11/12443.委托構(gòu)造函數(shù)的函數(shù)體中的語句在目標(biāo)構(gòu)造函數(shù)完全執(zhí)行后才被執(zhí)行。4.對(duì)象的生命期從任意一個(gè)構(gòu)造函數(shù)執(zhí)行完畢開始(對(duì)于委托構(gòu)造的情況,就是最終的目標(biāo)構(gòu)造函數(shù)執(zhí)行完畢時(shí)),這意味著從委托構(gòu)造函數(shù)體中拋出異常將導(dǎo)致析構(gòu)函數(shù)的自動(dòng)執(zhí)行。注意2023/11/12453.4.2析構(gòu)函數(shù)析構(gòu)函數(shù)的作用:在系統(tǒng)釋放對(duì)象之前進(jìn)行清理工作。析構(gòu)函數(shù)的特點(diǎn)析構(gòu)函數(shù)的函數(shù)名是固定的,由“~”+“類名”組成析構(gòu)函數(shù)沒有返回值析構(gòu)函數(shù)沒有參數(shù),因此析構(gòu)函數(shù)無法重載。一個(gè)類有且僅有一個(gè)析構(gòu)函數(shù)如果沒有自己寫出析構(gòu)函數(shù),系統(tǒng)會(huì)自動(dòng)生成一個(gè)析構(gòu)函數(shù)。合成析構(gòu)函數(shù)的函數(shù)體為空。2023/11/12463.4.2析構(gòu)函數(shù)析構(gòu)函數(shù)的特點(diǎn)析構(gòu)函數(shù)在對(duì)象生命周期結(jié)束時(shí)由系統(tǒng)自動(dòng)調(diào)用析構(gòu)函數(shù)的作用不是釋放對(duì)象,釋放對(duì)象是由系統(tǒng)來進(jìn)行的,而是在系統(tǒng)釋放對(duì)象之前進(jìn)行一些清理工作,把對(duì)象所占用的額外內(nèi)存空間歸還給系統(tǒng)注意2023/11/12473.4.2析構(gòu)函數(shù)如同構(gòu)造函數(shù)有一個(gè)初始化部分和一個(gè)函數(shù)體,析構(gòu)函數(shù)也有一個(gè)函數(shù)體和一個(gè)析構(gòu)部分。在一個(gè)構(gòu)造函數(shù)中,成員的初始化是在函數(shù)體執(zhí)行之前完成的,且按照它們?cè)陬愔谐霈F(xiàn)的順序進(jìn)行初始化。在一個(gè)析構(gòu)函數(shù)中,首先執(zhí)行函數(shù)體,然后析構(gòu)成員。成員按初始化順序的逆序析構(gòu)。在析構(gòu)函數(shù)的函數(shù)體內(nèi),可以書寫在對(duì)象最后一次使用之后類設(shè)計(jì)者希望執(zhí)行的任何收尾工作。通常,析構(gòu)函數(shù)的函數(shù)體完成釋放對(duì)象在生存期分配的所有資源。2023/11/12483.4.2析構(gòu)函數(shù)析構(gòu)部分是隱式的。成員析構(gòu)時(shí)發(fā)生什么完全依賴于成員的類型。析構(gòu)類類型的成員系統(tǒng)會(huì)自動(dòng)執(zhí)行成員對(duì)象自己的析構(gòu)函數(shù)。內(nèi)置類型沒有析構(gòu)函數(shù),因此析構(gòu)內(nèi)置類型成員什么也不需要做。注意:隱式析構(gòu)一個(gè)內(nèi)置指針類型的成員不會(huì)delete它所指向的對(duì)象。認(rèn)識(shí)到析構(gòu)函數(shù)體自身并不直接析構(gòu)成員是非常重要的。成員是在析構(gòu)函數(shù)體之后隱含的析構(gòu)階段中被析構(gòu)的。在整個(gè)對(duì)象被析構(gòu)過程中,析構(gòu)函數(shù)體是作為成員析構(gòu)步驟之外的另一部分進(jìn)行的。

2023/11/12493.4.2析構(gòu)函數(shù)【例3-11】簡化版的SalesData類。classSalesData//聲明圖書交易記錄類SalesData{public:

//受委托的構(gòu)造函數(shù),也稱為目標(biāo)構(gòu)造函數(shù)

SalesData(conststring&No,intn,doubleprice):bookNo(No),unitsSold(n),revenue(n*price){}

//其余構(gòu)造函數(shù)全部委托給另一個(gè)構(gòu)造函數(shù)

SalesData():SalesData("null",0,0){}

SalesData(conststring&No):SalesData(No,0,0){}

SalesData(istream&input):SalesData(){doubleprice; input>>bookNo>>unitsSold>>price; revenue=unitsSold*price;}……};2023/11/12503.4.2析構(gòu)函數(shù)【例3-11】簡化版的SalesData類。classSalesData

//聲明圖書交易記錄類SalesData{public:……~SalesData(){

//對(duì)象被銷毀前輸出圖書基本銷售記錄:書號(hào)、銷售冊(cè)數(shù)、總銷售金額、銷售均價(jià) cout<<"bookNo="<<bookNo; cout<<",unitsSold="<<unitsSold; cout<<",revenue="<<revenue; if(unitsSold!=0) cout<<",avgPrice="<<avgPrice(); cout<<endl;//換行}……};2023/11/12513.4.2析構(gòu)函數(shù)【例3-11】簡化版的SalesData類。classSalesData//聲明圖書交易記錄類SalesData{public:……

//計(jì)算圖書銷售均價(jià)doubleavgPrice(){returnrevenue/unitsSold;}private:stringbookNo; //書號(hào)intunitsSold; //銷售出的冊(cè)數(shù)doublerevenue;//總銷售額};intmain(){SalesDatabook1("1001",2,35.0);

SalesDatabook2("1002",5,32.6);return0;}程序執(zhí)行后運(yùn)行的結(jié)果如下:bookNo=1002,unitsSold=5,revenue=163,avgPrice=32.6bookNo=1001,unitsSold=2,revenue=70,avgPrice=352023/11/12523.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序總的原則當(dāng)創(chuàng)建對(duì)象時(shí)調(diào)用構(gòu)造函數(shù),當(dāng)釋放對(duì)象時(shí)調(diào)用析構(gòu)函數(shù)創(chuàng)建對(duì)象是當(dāng)程序執(zhí)行到了非靜態(tài)對(duì)象的定義語句或第一次執(zhí)行到靜態(tài)對(duì)象的定義語句釋放對(duì)象則是對(duì)象到了生命周期的最后時(shí)系統(tǒng)釋放對(duì)象或通過delete運(yùn)算符動(dòng)態(tài)釋放new運(yùn)算符動(dòng)態(tài)申請(qǐng)的對(duì)象2023/11/12533.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序【例3-12】驗(yàn)證調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序的例子。教材P962023/11/12543.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序下面對(duì)何時(shí)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的問題進(jìn)行小結(jié)。(1)在全局范圍中定義的對(duì)象(即在所有函數(shù)之外定義的對(duì)象),它的構(gòu)造函數(shù)在文件中的所有函數(shù)(包括main函數(shù))執(zhí)行之前調(diào)用。但如果一個(gè)程序中有多個(gè)文件,而不同的文件中都定義了全局對(duì)象,則這些對(duì)象的構(gòu)造函數(shù)的執(zhí)行順序是不確定的。當(dāng)main函數(shù)執(zhí)行完畢或調(diào)用exit函數(shù)時(shí)(此時(shí)程序終止),調(diào)用析構(gòu)函數(shù)。2023/11/12553.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序下面對(duì)何時(shí)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的問題進(jìn)行小結(jié)。(2)如果定義的是局部自動(dòng)對(duì)象(如在函數(shù)中定義對(duì)象),則在創(chuàng)建對(duì)象時(shí)調(diào)用其構(gòu)造函數(shù)。如果函數(shù)被多次調(diào)用,則在每次創(chuàng)建對(duì)象時(shí)都要調(diào)用構(gòu)造函數(shù)。在函數(shù)調(diào)用結(jié)束、釋放對(duì)象時(shí)先調(diào)用析構(gòu)函數(shù)。(3)如果在函數(shù)中定義靜態(tài)(static)局部對(duì)象,則只在程序第一次調(diào)用此函數(shù)創(chuàng)建對(duì)象時(shí)調(diào)用構(gòu)造函數(shù)一次,在調(diào)用結(jié)束時(shí)對(duì)象并不釋放,因此也不調(diào)用析構(gòu)函數(shù),只在main函數(shù)結(jié)束或調(diào)用exit函數(shù)結(jié)束程序時(shí),才調(diào)用析構(gòu)函數(shù)。2023/11/12563.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序構(gòu)造函數(shù)和析構(gòu)函數(shù)是類的兩個(gè)特殊的且非常重要的成員函數(shù),在設(shè)計(jì)一個(gè)類時(shí),應(yīng)盡可能考慮將來創(chuàng)建對(duì)象的各種情況,寫出多個(gè)構(gòu)造函數(shù),而對(duì)于類的析構(gòu)函數(shù),如果該類不包含指向動(dòng)態(tài)分配的內(nèi)存的指針數(shù)據(jù)成員,則可以不寫析構(gòu)函數(shù),如果該類包含指向動(dòng)態(tài)分配的內(nèi)存的指針數(shù)據(jù)成員,則必須寫析構(gòu)函數(shù),在析構(gòu)函數(shù)的函數(shù)體寫出釋放指針?biāo)赶騼?nèi)存空間的語句,否則會(huì)造成內(nèi)存泄漏??聪旅娴淖远x字符串類String。關(guān)于析構(gòu)函數(shù)的其他注意事項(xiàng),在本書第5章5.4.2節(jié)將會(huì)繼續(xù)介紹。2023/11/12燕京理工學(xué)院573.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序classString

//自定義字符串類{public:

String();//默認(rèn)構(gòu)造函數(shù)

String(unsignedint);

//帶一個(gè)無符號(hào)整型形參的構(gòu)造函數(shù),傳遞字符串的長度

String(char);//帶一個(gè)字符形參的構(gòu)造函數(shù),傳遞一個(gè)字符

String(constchar*src);

//帶一個(gè)字符指針形參的構(gòu)造函數(shù),傳遞一個(gè)字符串

~String();//析構(gòu)函數(shù)

char*toString(){returnstr;}//到普通字符串的轉(zhuǎn)換

unsignedintlength()//求字符串的長度

{returnlen;}

private:

char*str;

//字符指針str,將來指向動(dòng)態(tài)申請(qǐng)到的存儲(chǔ)字符串的內(nèi)存空間unsignedintlen;//字符串的長度};2023/11/12583.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序String::String(){len=0;str=newchar[len+1];

//指針str指向動(dòng)態(tài)申請(qǐng)到的內(nèi)存空間assert(str!=nullptr);

//如果括號(hào)內(nèi)表達(dá)式的值為假,則終止程序執(zhí)行

str[0]='\0';}2023/11/12593.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序//帶一個(gè)無符號(hào)整型形參的構(gòu)造函數(shù),傳遞字符串的長度String::String(unsignedintsize){assert(size>=0);len=size;str=newchar[len+1];assert(str!=nullptr);for(unsignedinti=0;i<len;i++)str[i]='\0';}2023/11/12603.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序String::String(charc)//帶一個(gè)字符形參的構(gòu)造函數(shù),傳遞一個(gè)字符{len=1;

str=newchar[len+1];

assert(str!=nullptr);

str[0]=c;

str[1]='\0';}String::String(constchar*src)//帶一個(gè)字符指針的構(gòu)造函數(shù),傳遞一個(gè)字符串{len=strlen(src);

str=newchar[len+1];

assert(str!=nullptr);

strcpy(str,src);}2023/11/12613.4.3

構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用次序String::~String()//析構(gòu)函數(shù){

delete[]str;str=nullptr;

//動(dòng)態(tài)釋放指針str所指向的內(nèi)存空間}2023/11/12623.5對(duì)象數(shù)組對(duì)象數(shù)組和普通的數(shù)組沒有本質(zhì)的區(qū)別,只不過普通的數(shù)組的元素是簡單變量,而對(duì)象數(shù)組的元素是對(duì)象而已對(duì)象數(shù)組在實(shí)際中主要用于系統(tǒng)需要一個(gè)類的多個(gè)對(duì)象的情況在建立數(shù)組時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用每一個(gè)對(duì)象元素的構(gòu)造函數(shù)2023/11/1263【例3-13】創(chuàng)建含有3個(gè)長方體元素的長方體數(shù)組,并顯示長方體構(gòu)造函數(shù)的調(diào)用情況。教材P993.5對(duì)象數(shù)組2023/11/12643.4.2析構(gòu)函數(shù)#include<iostream>usingnamespacestd;classBox{public:

Box(){……}

Box(floatL,floatw,floath){……}

~Box(){……}

floatvolume(){returnlength*width*height;}private:

floatlength,width,height;};intmain(){Boxboxs[3];//創(chuàng)建含有三個(gè)元素的對(duì)象數(shù)組boxsreturn0;}2023/11/12653.4.2析構(gòu)函數(shù)intmain(){Boxboxs[3];//創(chuàng)建含有三個(gè)元素的對(duì)象數(shù)組boxsreturn0;}程序執(zhí)行后運(yùn)行的結(jié)果如下:Box(1,1,1)isconstructed!Box(1,1,1)isconstructed!Box(1,1,1)isconstructed!Box(1,1,1)isdestructed!Box(1,1,1)isdestructed!Box(1,1,1)isdestructed!2023/11/12663.5對(duì)象數(shù)組對(duì)象數(shù)組在建立時(shí)還可以給出實(shí)參以實(shí)現(xiàn)對(duì)數(shù)組元素進(jìn)行不同的初始化如果Box類有只有一個(gè)參數(shù)的構(gòu)造函數(shù),可以使用如下形式的數(shù)組初始化形式:Boxboxs[3]={10,20,30};如果對(duì)象的構(gòu)造函數(shù)需要多個(gè)參數(shù),則在初始化的花括號(hào)里要分別寫明構(gòu)造函數(shù),并指定實(shí)參對(duì)象數(shù)組初始化參見【例3-14】2023/11/1267【例3-14】定義對(duì)象數(shù)組并初始化,觀察對(duì)象數(shù)組建立的情況。教材P1013.5對(duì)象數(shù)組2023/11/12683.4.2析構(gòu)函數(shù)#include<iostream>usingnamespacestd;classBox{public:

Box(){……}

Box(floatL,floatw,floath){……}

~Box(){……}

floatvolume(){returnlength*width*height;}private:

floatlength,width,height;};2023/11/12693.4.2析構(gòu)函數(shù)intmain(){//創(chuàng)建含有三個(gè)元素的對(duì)象數(shù)組boxesBoxboxs[3]={Box(1,3,5),Box(2,4,6),Box(3,6,9)};

//pbegin指向boxs數(shù)組的首元素,pend指向boxs數(shù)組尾元素的下一位置Box*pbegin=begin(boxs),*pend=end(boxs);

//遍歷對(duì)象數(shù)組boxs,計(jì)算并輸出每個(gè)Box類對(duì)象的體積while(pbegin!=pend){ cout<<"volume="<<pbegin->volume()<<endl; ++pbegin;}return0;}程序執(zhí)行后運(yùn)行的結(jié)果如下:Box(1,3,5)isconstructed!Box(2,4,6)isconstructed!Box(3,6,9)isconstructed!volume=15volume=48volume=162Box(3,6,9)isdestructed!Box(2,4,6)isdestructed!Box(1,3,5)isdestructed!2023/11/12703.4.2析構(gòu)函數(shù)intmain(){Boxboxs[3]={Box(1,3,5), Box(), Box(3,6,9)};//創(chuàng)建含有三個(gè)元素的對(duì)象數(shù)組boxsreturn0;}程序執(zhí)行后運(yùn)行的結(jié)果如下:Box(1,3,5)isconstructed!Box(1,1,1)isconstructed!Box(3,6,9)isconstructed!Box(3,6,9)isdestructed!Box(1,1,1)isdestructed!Box(1,3,5)isdestructed!2023/11/12713.6對(duì)象指針以指針的概念為基礎(chǔ),同時(shí)又加入了對(duì)象的特點(diǎn)對(duì)象與指針主要從三個(gè)方面進(jìn)行討論指向?qū)ο蟮闹羔樦赶驅(qū)ο蟪蓡T的指針this指針2023/11/12723.6.1指向?qū)ο蟮闹羔樦羔樦赶虻氖莾?nèi)存中對(duì)象所占用空間的首地址定義指向?qū)ο蟮闹羔樀囊话阈问绞牵侯惷?指針名;

通過指向?qū)ο蟮闹羔樤L問對(duì)象的成員有兩種形式通過“->”調(diào)用對(duì)象的公用成員函數(shù)通過“*”運(yùn)算符得到對(duì)象,然后再使用“.”運(yùn)算符調(diào)用對(duì)象的公用成員函數(shù)2023/11/12733.6.2指向?qū)ο蟪蓡T的指針指向?qū)ο髷?shù)據(jù)成員的指針指向?qū)ο髷?shù)據(jù)成員的指針和普通的指針是完全相同的,聲明指針變量的格式如下:

數(shù)據(jù)類型名*指針變量名;而使指針指向?qū)ο蟮墓脭?shù)據(jù)成員使用如下語句:

指針變量=&對(duì)象名.數(shù)據(jù)成員名;設(shè)類A有公用整型數(shù)據(jù)成員data,定義了一個(gè)整型指針p和A類對(duì)象a,則p=&a.data;//使整型指針p指向?qū)ο骯的數(shù)據(jù)成員datacout<<*p<<endl;2023/11/12743.6.2指向?qū)ο蟪蓡T的指針指向?qū)ο蟪蓡T函數(shù)的指針指向?qū)ο蟪蓡T函數(shù)的指針需要在指針名前面加上所屬的類名及域運(yùn)算符“::”指向?qū)ο蟪蓡T函數(shù)的指針不但要匹配將要指向函數(shù)的參數(shù)類型、個(gè)數(shù)和返回值類型,還要匹配將要指向函數(shù)所屬的類2023/11/12753.6.2指向?qū)ο蟪蓡T的指針指向普通函數(shù)的指針變量定義如下:

返回值類型(*指針名)(參數(shù)表);而指向成員函數(shù)的指針變量定義如下:

返回值類型(類名::*指針名)(參數(shù)表);使用指向成員函數(shù)的指針指向一個(gè)公用成員函數(shù)時(shí)如下:

指針名=&類名::成員函數(shù)名;使用指向成員函數(shù)的指針調(diào)用對(duì)象的成員函數(shù)時(shí)如下:

(對(duì)象名.*指針名)(實(shí)參表);2023/11/12763.6.2指向?qū)ο蟪蓡T的指針【例3-15】使用指向?qū)ο蟪蓡T函數(shù)的指針調(diào)用對(duì)象的成員函數(shù).intmain(){Boxbox(2,2,2); //創(chuàng)建Box的對(duì)象box//定義指向Box類的成員函數(shù)的指針pfloat(Box::*p)();

//給指針p賦值,使其指向Box類的成員函數(shù)Volume

p=&Box::volume;

//調(diào)用指針p指向的函數(shù)cout<<“Thevolumeofboxis"<<(box.*p)()<<endl;

return0;}2023/11/12773.6.2指向?qū)ο蟪蓡T的指針(1)在給指向?qū)ο蟪蓡T函數(shù)的指針進(jìn)行賦值時(shí)要把類的函數(shù)名賦值給指針,而不是對(duì)象的函數(shù)名(2)調(diào)用指向?qū)ο蟪蓡T函數(shù)的指針指向的成員函數(shù)時(shí),要通過(對(duì)象名.*指針名)(實(shí)參表)的形式,而不是(類名.*指針名)(實(shí)參表)的形式。(3)定義指向?qū)ο蟪蓡T函數(shù)的指針時(shí)可以同時(shí)進(jìn)行初始化操作,形式為:返回值類型(類名::*指針名)(形參表)=&類名::成員函數(shù)名;如:float(Box::*p)()=&Box::Volume;注意2023/11/12783.6.3

this指針在每一個(gè)成員函數(shù)中都包含了一個(gè)特殊指針,這個(gè)指針的名字是固定的,稱為this指針。如Box類中的volume函數(shù),其中的height*width*length實(shí)際上是(this->height)*(this->width)*(this->length)this指針是指向本類對(duì)象的指針,它的指向是被調(diào)用成員函數(shù)所在的對(duì)象this指針是由系統(tǒng)通過參數(shù)隱式傳遞給成員函數(shù)的2023/11/1279this指針的處理過程源程序編譯后調(diào)用時(shí)floatBox::volume(){returnlength*width*height;}floatBox::volume(Box*this){returnthis->length*this->width*this->height;}box1.volume(&box1);2023/11/12803.7對(duì)象與const在程序設(shè)計(jì)的過程中需要考慮的一個(gè)非常重要的因素就是數(shù)據(jù)的安全性在程序中,不同的模塊之間經(jīng)常出現(xiàn)需要共享數(shù)據(jù)的情況,此時(shí)數(shù)據(jù)的安全性降低在程序中既要讓數(shù)據(jù)在一定范圍內(nèi)共享,又要保證數(shù)據(jù)的安全,這時(shí)可以使用const,把對(duì)象或?qū)ο笙嚓P(guān)成員定義成常量本節(jié)主要從常對(duì)象、常對(duì)象成員、指向?qū)ο蟮某V羔?、指向常?duì)象的指針和對(duì)象的常引用五個(gè)方面進(jìn)行說明2023/11/12813.7.1常對(duì)象常對(duì)象中的所有成員的值都不能被修改常對(duì)象中數(shù)據(jù)成員為常變量且必須有初值聲明常對(duì)象的一般形式const類名對(duì)象名[(實(shí)參表)];類名const對(duì)象名[(實(shí)參表)];如果一個(gè)對(duì)象被聲明為常對(duì)象,則不能調(diào)用該對(duì)象的非const型的成員函數(shù)(構(gòu)造函數(shù)和析構(gòu)函數(shù)除外)在成員函數(shù)聲明的后面加上const即可訪問2023/11/12823.7.1常對(duì)象如何將一個(gè)成員函數(shù)聲明成const型成員函數(shù)呢?其實(shí)很簡單,只需要在成員函數(shù)聲明的后面加上const即可。floatvolume()const;特別提醒:有時(shí)在編程時(shí)有要求,一定要修改常對(duì)象中的某個(gè)數(shù)據(jù)成員的值,ANSIC++考慮到實(shí)際編程時(shí)的需要,對(duì)此作了特殊的處理,將該數(shù)據(jù)成員聲明為mutable,如:mutableintcount;把count聲明為可變的數(shù)據(jù)成員,這樣就可以用聲明為const的成員函數(shù)來修改它的值。2023/11/12833.7.2常對(duì)象成員常數(shù)據(jù)成員常數(shù)據(jù)成員的聲明和作用與普通的常變量類似在程序運(yùn)行過程中常數(shù)據(jù)成員的值不能修改常變量在聲明的同時(shí)必須初始化注意常數(shù)據(jù)成員在初始化時(shí)必須使用構(gòu)造函數(shù)的參數(shù)初始化表2023/11/12843.7.2常對(duì)象成員例:若Box類中的數(shù)據(jù)成員length聲明為常數(shù)據(jù)成員,則如下的構(gòu)造函數(shù):Box::Box(floatL,floatw,floath){length=L;

width=w; height=h;}×不能使用這種形式進(jìn)行初始化Box::Box(floatL,floatw,floath):length(L){width=w; height=h;}√2023/11/12853.7.2常對(duì)象成員常成員函數(shù)就是const型成員函數(shù)聲明常成員函數(shù)的一般形式:返回值類型成員函數(shù)名(形參表)const;常成員函數(shù)只能訪問而不能修改數(shù)據(jù)成員的值,如果在常成員函數(shù)中出現(xiàn)了修改數(shù)據(jù)成員值的語句,系統(tǒng)編譯是通不過的。2023/11/12863.7.2常對(duì)象成員常成員函數(shù)非常成員函數(shù)常數(shù)據(jù)成員可以訪問,但不可修改值可以訪問,但不可修改值非常數(shù)據(jù)成員可以訪問,但不可修改值可以訪問,也可以修改值數(shù)據(jù)成員分類成員函數(shù)分類2023/11/12873.7.2常對(duì)象成員(1)在一個(gè)類中可以根據(jù)需要將部分?jǐn)?shù)據(jù)成員聲明為const數(shù)據(jù)成員,另一部分?jǐn)?shù)據(jù)成員為非const數(shù)據(jù)成員。(2)如果一個(gè)類的所有數(shù)據(jù)成員都不允許修改,可以將這個(gè)類中的所有數(shù)據(jù)成員都聲明成const型數(shù)據(jù)成員,或者定義對(duì)象時(shí)聲明為const對(duì)象,兩者都可以保證對(duì)象的數(shù)據(jù)成員的安全。注意2023/11/12883.7.2常對(duì)象成員(3)常對(duì)象中的數(shù)據(jù)成員都是const型數(shù)據(jù)成員,但是常對(duì)象中的成員函數(shù)不一定都是const型成員函數(shù),只有在成員函數(shù)的聲明和定義部分有const關(guān)鍵字的才是const型成員函數(shù)。注意2023/11/12893.7.2常對(duì)象成員(4)如果已定義了一個(gè)常對(duì)象,只能調(diào)用其中的const型成員函數(shù)。如果一個(gè)成員函數(shù)沒有修改數(shù)據(jù)成員,但是沒有聲明為const型成員函數(shù),也不能通過常對(duì)象名調(diào)用。因此,如果在使用一個(gè)類的對(duì)象時(shí)可能會(huì)聲明const對(duì)象,則在定義類時(shí)應(yīng)該將那些不會(huì)修改數(shù)據(jù)成員的成員函數(shù)聲明為const型,否則如果該類中沒有公用的const型成員函數(shù),則聲明了該類的const對(duì)象之后將無法調(diào)用任何一個(gè)成員函數(shù)。(5)在類的定義中,const型成員函數(shù)不能調(diào)用非const型成員函數(shù)。注意2023/11/12903.7.3指向?qū)ο蟮某V羔槍⒅赶驅(qū)ο蟮闹羔樧兞柯暶鳛閏onst型定義指向?qū)ο蟮某V羔樀囊话阈问剑侯惷?const指針名[=&類的對(duì)象];例如:Boxbox(2,2,2);Box*constpbox=&box;在給pbox賦初值后pbox的值不能再修改2023/11/12913.7.3指向?qū)ο蟮某V羔樢话闱闆r下指向?qū)ο蟮腸onst指針用作函數(shù)的形參指針在函數(shù)的執(zhí)行過程中不會(huì)改變指針的指向可以防止誤操作,增加系統(tǒng)的安全性2023/11/12923.7.4指向常對(duì)象的指針變量指向常對(duì)象的指針變量和指向常變量的指針變量的概念和用法非常接近定義指向常對(duì)象的指針變量的一般形式:const類名*指針變量名;說明:(1)如果一個(gè)對(duì)象已被聲明為常對(duì)象,只能用指向常對(duì)象的指針變量指向它,而不能用一般的(指向非const型對(duì)象的)指針變量去指向它2023/11/12933.7.4指向常對(duì)象的指針變量classClock//聲明時(shí)鐘類Clock{public:Clock(inth,intm,ints)//帶有3個(gè)形參的構(gòu)造函數(shù){hour=h;minute=m;second=s;}voiddisplay()//公用成員函數(shù)display顯示時(shí)間{cout<<hour<<":"<<minute<<":"<<second<<endl;}inthour,minute,second;//公用數(shù)據(jù)成員};intmain(){//定義Clock類對(duì)象clock1,它是常對(duì)象constClockclock1(1,1,1);constClock*p1=&clock1;//正確,clock1是常對(duì)象,p1是指向常對(duì)象的指針//Clock*p2=&clock1;//錯(cuò)誤,clock1是常對(duì)象,而p2是普通指針

……return0;}2023/11/12943.7.4指向常對(duì)象的指針變量說明:(2)如果定義了一個(gè)指向常對(duì)象的指針變量,并使它指向一個(gè)非const的對(duì)象,則其指向的對(duì)象是不能通過指針來改變的Clockclock2(2,2,2);constClock*p2=&clock2;//正確//正確,通過p2可以訪問clock2對(duì)象的數(shù)據(jù)成員的值cout<<p2->hour<<endl;//錯(cuò)誤,不能通過p2修改clock2對(duì)象的數(shù)據(jù)成員的值p2->hour=2;p2->display();//錯(cuò)誤,display是非const型成員函數(shù)2023/11/12953.7.4指向常對(duì)象的指針變量說明:(3)如果定義了一個(gè)指向常對(duì)象的指針變量,雖然不能通過它改變所指向的對(duì)象的值,但是指針變量本身的值是可以改變的Clockclock3(3,3,3);Clockclock4(4,4,4);//定義指向常對(duì)象的指針變量p3,并指向?qū)ο骳lock3constClock*p3=&clock3;//正確,p3改為指向?qū)ο骳lock4p3=&clock4;2023/11/12963.7.4指向常對(duì)象的指針變量說明:(4)指向常對(duì)象的指針變量最常用于函數(shù)的形參,目的是在保護(hù)形參指針?biāo)赶虻膶?duì)象,使它在函數(shù)執(zhí)行過程中不被修改2023/11/12973.7.4指向常對(duì)象的指針變量classClock//聲明時(shí)鐘類Clock{public:Clock(inth,intm,ints)//帶有3個(gè)形參的構(gòu)造函數(shù){hour=h;minute=m;second=s;}voiddisplay()//公用成員函數(shù)display顯示時(shí)間{cout<<hour<<":"<<minute<<":"<<second<<endl;}inthour,minute,second;//公用數(shù)據(jù)成員};intmain(){//函數(shù)func的形參為指向常對(duì)象的指針voidfunc(constClock*p);

//定義Clock類對(duì)象clock,它不是常對(duì)象Clockclock(10,10,10);func(&clock);//實(shí)參為對(duì)象clock的地址return0;}voidfunc(constClock*p){p->hour=12;//錯(cuò)誤cout<<p->hour<<endl;//正確}2023/11/12983.7.4指向常對(duì)象的指針變量請(qǐng)記住這樣一條規(guī)則:當(dāng)希望在調(diào)用函數(shù)時(shí)參數(shù)對(duì)象的值不被修改,就應(yīng)當(dāng)把形參定義為指向常對(duì)象的指針變量,同時(shí)用對(duì)象的地址作實(shí)參,而對(duì)象參數(shù)可以是const或非const型。2023/11/12993.7.5對(duì)象的常引用對(duì)象的常引用表示一個(gè)對(duì)象的別名,但是無法通過引用來修改對(duì)象的數(shù)據(jù)成員聲明對(duì)象的常引用的一般形式:const類名&引用名=對(duì)象名;常引用的應(yīng)用也是主要用在函數(shù)的形參中,保證函數(shù)調(diào)用時(shí)實(shí)參對(duì)象的安全性例如:Clockclock(12,12,12);constClock&refclock=clock;refclock.Display();2023/11/121003.8對(duì)象的動(dòng)態(tài)創(chuàng)建和釋放使用new和delete運(yùn)算符實(shí)現(xiàn)對(duì)對(duì)象的動(dòng)態(tài)創(chuàng)建與釋放對(duì)于例3-14程序中聲明的長方體類Box,可以使用如下語句動(dòng)態(tài)地創(chuàng)建一個(gè)Box類的對(duì)象:newBox;在程序執(zhí)行到new語句時(shí),系統(tǒng)會(huì)從內(nèi)存堆中分配一塊內(nèi)存空間,存放類的對(duì)象,調(diào)用構(gòu)造函數(shù)初始化對(duì)象。如果內(nèi)存分配成功,返回分配的內(nèi)存的首地址;如果分配內(nèi)存失敗,則會(huì)返回一個(gè)nullptr。2023/11/121013.8對(duì)象的動(dòng)態(tài)創(chuàng)建和釋放但是通過new運(yùn)算符動(dòng)態(tài)創(chuàng)建的對(duì)象沒有名字,要聲明一個(gè)指針變量來保存對(duì)象的首地址。如:Box*pc=newBox;2023/11/121023.8對(duì)象的動(dòng)態(tài)創(chuàng)建和釋放可以在使用new運(yùn)算符創(chuàng)建對(duì)象時(shí)給出實(shí)參,調(diào)用帶有參數(shù)的構(gòu)造函數(shù)初始化對(duì)象如:Box*pc=newBox(2,2,2);

為了保險(xiǎn)起見,在使用對(duì)象指針之前一般先判斷指針的值是否為nullptr。如下所示:Box*pc=newBox(2,2,2);if(pc!=nullptr){pc->volume();}2023/11/121033.8對(duì)象的動(dòng)態(tài)創(chuàng)建和釋放使用delete運(yùn)算符釋放該對(duì)象delete運(yùn)算符的使用格式是:delete指針變量名;如:deletepc;通過new運(yùn)算符動(dòng)態(tài)創(chuàng)建的對(duì)象只能通過delete運(yùn)算符動(dòng)態(tài)的釋放2023/11/121043.9對(duì)象的復(fù)制和賦值在創(chuàng)建對(duì)象時(shí)使用已有對(duì)象快速復(fù)制出完全相同的對(duì)象對(duì)象復(fù)制的一般形式類名對(duì)象2(對(duì)象1);類名對(duì)象2=對(duì)象1;其中對(duì)象1是和對(duì)象2同類的已經(jīng)存在的對(duì)象。上面語句的作用就是使用已經(jīng)存在的對(duì)象1“克隆”出新的對(duì)象2。在這種情況下,創(chuàng)建對(duì)象2時(shí)系統(tǒng)會(huì)調(diào)用一個(gè)稱為“復(fù)制構(gòu)造函數(shù)”的特殊的構(gòu)造函數(shù)。3.9.1對(duì)象的復(fù)制2023/11/12105以Box類為例,看看復(fù)制構(gòu)造函數(shù)的形式:Box::Box(constBox&c)//Box類的復(fù)制構(gòu)造函數(shù){length=c.length;width=c.width;height=c.height;}3.9對(duì)象的復(fù)制和賦值3.9.1對(duì)象的復(fù)制復(fù)制構(gòu)造函數(shù)只有一個(gè)形參,這個(gè)形參就是本類對(duì)象的引用復(fù)制構(gòu)造函數(shù)的代碼主要是將形參中對(duì)象引用的各數(shù)據(jù)成員值賦給自己的數(shù)據(jù)成員2023/11/121063.9.1對(duì)象的復(fù)制如果用戶自己沒有定義復(fù)制構(gòu)造函數(shù),編譯器會(huì)隱式地提供一個(gè)。與合成默認(rèn)構(gòu)造函數(shù)不同,即使定義了其他構(gòu)造函數(shù),編譯器也會(huì)合成一個(gè)復(fù)制構(gòu)造函數(shù),它會(huì)將實(shí)參對(duì)象中的非static數(shù)據(jù)成員逐個(gè)復(fù)制到正在創(chuàng)建的對(duì)象中。每個(gè)成員的類型決定了它如何復(fù)制:類類型的成員,會(huì)使用其復(fù)制構(gòu)造函數(shù)來復(fù)制;內(nèi)置類型的成員則直接復(fù)制。對(duì)于數(shù)組,合成復(fù)制構(gòu)造函數(shù)會(huì)逐元素地復(fù)制一個(gè)數(shù)組類型的成員。如果數(shù)組元素是類類型,則使用元素的復(fù)制構(gòu)造函數(shù)來進(jìn)行復(fù)制。2023/11/12燕京理工學(xué)院1073.9.1對(duì)象的復(fù)制普通構(gòu)造函數(shù)和復(fù)制構(gòu)造函數(shù)的區(qū)別:(1)在形式上普通構(gòu)造函數(shù)一般是形參列表而復(fù)制構(gòu)造函數(shù)的形參則只有一個(gè)(2)在調(diào)用時(shí)系統(tǒng)會(huì)根據(jù)實(shí)參類型來自動(dòng)的選擇調(diào)用普通構(gòu)造函數(shù)還是復(fù)制構(gòu)造函數(shù)。(3)調(diào)用的情況不同,普通構(gòu)造函數(shù)是在創(chuàng)建對(duì)象時(shí)由系統(tǒng)自動(dòng)調(diào)用;而復(fù)制構(gòu)造函數(shù)是在使用已有對(duì)象復(fù)制一個(gè)新對(duì)象時(shí)由系

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論