版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第4章繼承性授課內(nèi)容4.1繼承與派生的概念4.2
派生類的聲明方式4.3
派生類的構成4.4派生類中基類成員的訪問屬性4.5派生類相對于基類的變化4.6
派生類的構造函數(shù)和析構函數(shù)4.7基類與派生類對象的關系4.8多重繼承4.1繼承與派生的概念8.1繼承與派生為什么使用繼承?(具體化、特殊化)使用繼承,可實現(xiàn)代碼的重用,進而提高代碼的易維護性。水果桃梨蘋果萊陽梨紅富士秦冠繼承性概述兩個類之間的一種關系,當一個類擁有另一個類的所有屬性和行為時,就稱這兩個類之間具有繼承關系。被繼承的類稱為父類或基類,繼承了父類屬性和行為的類稱為子類或派生類。繼承性概述Question:如何設計類?行為吃飯、睡覺、講課屬性身高、體重、講授課程教師行為吃飯、睡覺、聽課屬性身高、體重、所在班級學生行為吃飯、睡覺屬性身高、體重人繼承性概述行為講課屬性講授課程教師:繼承人行為聽課屬性所在班級學生:繼承人行為吃飯、睡覺屬性身高、體重人繼承性概述派生類繼承了基類除構造函數(shù)與析構函數(shù)之外的全部成員。派生類可以改造基類的成員繼承性概述根據(jù)基類的個數(shù),繼承分為:單繼承:子類只有一個直接基類。ShapeTwoDShapeThreeDShapeCircleSquareTriangle繼承性概述根據(jù)基類的個數(shù),繼承分為:多繼承:子類有多個直接基類。職員在職研究生研究生設計程序時盡量少使用多繼承?;惡团缮惖年P系,可以表述為:
派生類是基類的具體化,而基類是派生類的抽象。4.1繼承與派生的概念4.2派生類的聲明方式4.2派生類的聲明方式根據(jù)繼承的方式,繼承分為:公有繼承私有繼承:默認方式保護繼承派生類的定義格式:class派生類名
:繼承方式基類1,繼承方式基類2,…{ 派生類中增加的成員聲明與定義; };4.2派生類的聲明方式4.編程舉例:classPerson{protected: stringm_szName; stringm_szSex;public: voidShowP() {cout<<m_szName<<"\t"<<m_szSex<<endl; }};classEmployee:publicPerson{ stringm_szDept;public: voidShowE() {cout<<m_szName<<"\t"<<m_szSex<<"\t"<<m_szDept<<endl; } };Employeeemp;emp.ShowP();emp.ShowE();4.2派生類的聲明方式5.編程舉例:多繼承classPlane{ charchPropeller;public: voidFlight();};classBoat{ charchHelm;public: voidFloat();};classSeaplane :publicPlane,publicBoat{ };編程實現(xiàn)4.3派生類的構成派生類中的成員包括:從基類繼承過來的成員自己新增加的成員從基類繼承過來的成員體現(xiàn)了派生類從基類繼承而獲得的共性,而新增加的成員體現(xiàn)了派生類的個性,體現(xiàn)了派生類與基類的不同,體現(xiàn)了不同派生類的區(qū)別。4.3派生類的構成4.3派生類的構成派生類對象的構成公有成員保護成員私有成員公有成員保護成員私有成員繼承部分新定義部分派生類成員派生類classBase
//聲明基類{public://基類公用成員
voidsetx(intn){x=n;}
int
getx(){returnx;}voidshowx(){cout<<"Baseclass:x="<<x<<endl;}private://基類私有成員
intx;};第4章繼承與組合//以public方式聲明派生類Derived
classDerived:
publicBase{public:voidsety(intn){y=n;}
int
gety(){returny;}voidshowy()
{cout<<"Derivedclass:y="<<y<<endl;}private:
inty;};第4章繼承與組合第4章繼承與組合圖4-3基類Base和派生類Derived的成員示意圖
voidsetx();
int
getx();voidshowx();
intx;Base類
voidsetx();
int
getx();voidshowx();intx;Derived類
voidsety();
int
gety();voidshowy();inty;繼承新增數(shù)據(jù)成員成員函數(shù)注:ClassA{public:
intx;};ClassB:publicA{public;
inty;};Bb;ClassC{public:
intx,y;};可否認為b是C類的對象?邏輯上可以,本質上不是。實際上,對象b創(chuàng)建過程中會首先創(chuàng)建一個基類A的隱含對象。實際上,并不是把基類的成員和派生類自己新增加的成員簡單地加在一起就成為派生類。構造一個派生類一般經(jīng)歷3個步驟:
1.從基類接收成員
2.調(diào)整從基類接收的成員
3.增加新成員。4.3派生類的構成Question:某信息管理系統(tǒng)中,定義人Person類,包括數(shù)據(jù)成員:姓名、年齡,成員函數(shù):獲得年齡、信息設置、信息顯示;另外,需要定義學生Student類,包括數(shù)據(jù)成員:姓名、年齡、學號,成員函數(shù):獲得年齡、獲得學號、信息設置、信息顯示。請定義Person類和Student類。classPerson{ stringm_sName;
int
m_iAge;public:
int
GetAge()const;voidSet(stringname,intage); voidShow()const;};classStudent:Person?{
int
m_iNumber;public:
int
GetNumber()const;voidSetStudent(stringname,intage,intnumber);voidShowStudent()const;};采用哪種繼承方式?4.4派生類的繼承方式派生類的繼承方式—回顧classTest{
inta1; voidf1(){cout<<a1;}proteced:
inta2; voidf2(){cout<<a2;}public:
inta3; voidf3(){cout<<a3;} voidshow{f1();f2();f3()}};intmain(){Testt;
cout<<t.a1;
cout<<t.a2;
cout<<t.a3;t.f1();t.f2();t.f3();
t.show();return0;}派生類的繼承方式(訪問權修飾符)繼承方式
public:
公有繼承
protected:
保護繼承
private:
私有繼承通過繼承方式,可以調(diào)整從基類中繼承下來的成員的訪問控制權限。公有繼承繼承方式基類成員訪問權限繼承到派生類后訪問權限公有繼承
publicpublicprotectedprotectedprivate不可訪問編程舉例
Classx{Private:
inta;Protected:
intb;Public:
intc;};y1的構成:不可訪問:私有:保護:公有:Classy1:publicx{
intd;};adbc保護繼承繼承方式基類成員訪問權限繼承到派生類后訪問權限保護繼承
publicprotectedprotectedprotectedprivate不可訪問編程舉例
Classx{Private:
inta;Protected:
intb;Public:
intc;};y1的構成:不可訪問:私有:保護:公有:Classy1:protectedx{
intd;};adbc私有繼承繼承方式基類成員訪問權限繼承到派生類后訪問權限私有繼承
publicprivateprotectedprivateprivate不可訪問編程舉例
Classx{Private:
inta;Protected:
intb;Public:
intc;};y1的構成:不可訪問:私有:保護:公有:Classy1:publicx{
intd;};adbc程序改錯classA{
int
m_Private;protected:
int
m_Protected;public:
int
m_Pulbic;};int
main(){Bb;b.SetNum();
b.m_Public=10;
b.m_protected=10;
b.m_Private=10;return0;}classB:publicA{public: voidSetNum() {m_Protected=1;
m_Pulbic=1;
m_Private=1; }};classA{
int
m_Private;protected:
int
m_Protected;public:
int
m_Pulbic;};int
main(){Bb;b.SetNum();
b.m_Pulbic=10;
b.m_protected=10;
b.m_Private=10;return0;}classB:protectedA{public: voidSetNum() {m_Protected=1;
m_Pulbic=1;
m_Private=1; }};多層繼承ex8_inherit
classA{public:voidf1();protected:intj1;private:inti1;};classB:publicA{public:voidf2();protected:intj2;private:inti2;};classC:publicB{public:voidf3();};1.f2()能否訪問基類A中的成員:f1(),i1,j1?可以訪問f1(),j1,不可訪問i1;2.派生類B的對象b1能否訪問基類A中的成員:f1(),i1,j1?可以訪問f1(),不可訪問i1和j1;3.f3()能否訪問直接基類B中的成員:f2(),j2和i2?能否訪問間接基類A中的成員:f1(),j1和i1?可以訪問f2()和j2,f1()和j1,不可訪問i1和i2;4.C類的對象c1能否訪問f2(),i2,j2?能否訪問f1(),i1,j1?可以訪問f2()和f1();classA{
int
m_Private;protected:
int
m_Protected;public:
int
m_Pulbic;};int
main(){Bb;b.SetNum();
b.m_Pulbic=10;
b.m_protected=10;
b.m_Private=10;return0;}classB:privateA{public: voidSetNum() {m_Protected=1;
m_Pulbic=1;
m_Private=1; }};結論:在公有繼承時,派生類的成員函數(shù)可訪問基類中的公有成員和保護成員,派生類對象僅可訪問基類中的公有成員。思考:將兩處public改為private呢?練習:My8_2classPerson{ stringm_sName;
int
m_iAge;public:
int
GetAge()const;voidSet(stringname,intage); voidShow()const;};classStudent:Person?{
int
m_iNumber;public:
int
GetNumber()const;voidSetStudent(stringname,intage,intnumber);voidShowStudent()const;};采用哪種繼承方式?privateprotectedpublic如何實現(xiàn)?voidShowStudent(){cout<<"Name:"<<m_sName<<"Age:"<<m_iAge
<<"Number:"<<m_iNumber
<<endl; }protected:
編程注意:
當不允許外部訪問一個類的數(shù)據(jù)成員,而允許該類的派生類訪問該數(shù)據(jù)成員時,把數(shù)據(jù)成員定義為保護成員編程實現(xiàn)classPerson{ stringm_sName;
int
m_iAge;public:
int
GetAge()const;voidSet(stringname,intage); voidShow()const;};classStudent:publicPerson{ int
m_iNumber;public:
int
GetNumber()const;voidSetStudent(stringname,intage,intnumber); voidShowStudent();};protected:Show()const;
SetStudentstudent1;Student1.Show();Student1.Set(“LiYang”,20);
4.5派生類相對于基類的變化派生類相對于基類的變化派生類相對于基類的變化,主要體現(xiàn)在:派生類對基類的擴充派生類中的成員對基類成員的隱藏派生類對基類的擴充增加新成員classP//人{protected: charname[10];
intsex;public: voidShowP() {
cout<<name <<sex; }};classE:publicP//員工{chardept[20];public:
voidShowE(){
cout<<name <<sex <<dept;} };Eemp;emp.ShowP();emp.ShowE();派生類對基類的擴充集合基類成員classPlane{ charchPropeller;public: voidFlight();};classBoat{ charchHelm;public: voidFloat();};classSeaplane:publicPlane,publicBoat{};Seaplanesp;sp.Flight();sp.Float();派生類相對于基類的變化派生類相對于基類的變化,主要體現(xiàn)在:派生類對基類的擴充派生類中的成員對基類成員的隱藏派生類中的成員對基類成員的隱藏classP//人{protected: charname[10];
intsex;public: voidShowP() {
cout<<name <<sex; }};Eemp;emp.ShowP();emp.ShowE();classE:publicP//員工{chardept[20];public:voidShowE(){
cout<<name <<sex <<dept;} };Show()Show()Eemp;emp.Show();classB{protected:
int
mb;intma;public: B(intx,inty) :mb(x),ma(y) {}};classD:publicB{int
md;
intma;public:D(intj,intk,intl,intm) :B(j,k),md(l),ma(m){}voidSetA(intv){ma=v;}
int
GetA()const{returnma;}};intmain(){Dod(1,2,3,4);
cout<<od.GetA();
od.SetA(100);
cout<<od.GetA();return0;}指D中的maclassB{protected:
int
mb;public: B(intx):mb(x) {} voidSet(intx) {mb=x;}};classD:publicB{int
md;public:
D(intj,intk):B(j),md(k){}voidSet(intx,inty){mb=x;md=y;}voidPrint()const{cout<<mb<<md;}};intmain(){Dod(1,2);od.Print();
od.Set(10);od.Print();
od.Set(100,200);od.Print();return0;}調(diào)用出錯派生類中的成員對基類成員的隱藏結論如果派生類定義的某個成員的名字和基類中的某個成員的名字相同,則稱派生類隱藏了基類同名的成員。注意:無論派生類與基類的同名成員函數(shù)的參數(shù)是否相同,派生類都會隱藏基類同名的成員。classB{protected:
int
mb;public: B(intx):mb(x) {} voidSet(intx) {mb=x;}};classD:publicB{int
md;public:
D(intj,intk):B(j),md(k){}voidSet(intx,inty){mb=x;md=y;}voidPrint()const{cout<<mb<<md;}};intmain(){Dod(1,2);od.Print();
od.Set(10);od.Print();
od.Set(100,200);od.Print();return0;}調(diào)用出錯Question:派生類D對象如何訪問基類B的set函數(shù)?派生類中的成員對基類成員的隱藏Question:如何訪問基類中被隱藏的數(shù)據(jù)成員?Answer:顯示訪問基類成員
顯式訪問基類成員How?類成員訪問方式隱式訪問“對象名.成員名”或“成員名”。顯式訪問類名::成員名舉例:emp.ShowMe();//emp.Employee::ShowMe();returnm_szName;//returnPerson::m_szName;
顯式訪問基類成員When?派生類對基類成員的顯式訪問派生類與基類有重名的成員,顯式訪問某個成員。派生類employee的成員函數(shù)ShowMevoidShowMe()//派生類與基類都有ShowMe(){ Person::ShowMe();
cout<<"something"<<endl;}顯式訪問基類成員
When?多繼承派生,多個基類中有同名成員,將在派生類中產(chǎn)生歧義性,通過顯式訪問消除歧義性。classA {public: charm_szName[20];…}classB {public: charm_szName[20];…}classC:publicA,publicB { … }char*C::GetName(){ returnm_szName;}//Error!char*C::GetName(){ returnA::m_szName;}//
OK!多繼承派生類具有多個基類。基類1基類2基類n…派生類classPerson{ stringm_sName;
int
m_iAge;public:
int
GetAge()const;voidSet(stringname,intage); voidShow()const;};classStudent:publicPerson{ int
m_iNumber;public:
int
GetNumber()const;voidSetStudent(stringname,intage,intnumber); voidShowStudent();};protected:Show()const;
SetStudentstudent1;student1.Show();student1.Set(“LiYang”,20);//student1.Student::Show();
//error!student1.Person::Set(“LiYang”,20);練習:實現(xiàn)Student類中的Set和Show函數(shù)。voidStudent::Set(stringname,intage,intnumber){
Person::Set(name,age);
m_iNumber=number;}voidStudent::Show(){
Person::Show();
cout<<"Number:"<<m_iNumber<<endl;}Question:為Person類和Student類添加構造函數(shù),可以初始化Person類和Student類對象。4.6派生類的構造函數(shù)和析構函數(shù)派生類的構造函數(shù)和析構函數(shù)回顧:派生類不繼承構造函數(shù)和析構函數(shù)派生類的組成?公有成員保護成員私有成員公有成員保護成員私有成員繼承部分新定義部分派生類成員注意:以基類子對象的形式存在派生類的構造函數(shù)與析構函數(shù)回顧:派生類對象的創(chuàng)建過程231首先,創(chuàng)建基類的隱含對象然后,創(chuàng)建內(nèi)嵌對象(如果存在)最后,創(chuàng)建派生類對象派生類的構造函數(shù)與析構函數(shù)回顧:派生類對象的撤銷過程3首先,撤銷基類的隱含對象2然后,撤銷內(nèi)嵌對象(如果存在)1首先撤消派生類對象
派生類的構造函數(shù)與析構函數(shù)概述派生類新增成員的初始化工作,由派生類的構造函數(shù)完成。從基類繼承的成員的初始化工作,由基類的構造函數(shù)完成。必須在派生類中對基類的構造函數(shù)所需要的參數(shù)進行設置。思考:基類構造函數(shù)的調(diào)用應該在何時?在派生類構造函數(shù)體中可以嗎?派生類構造函數(shù)派生類::派生類(參數(shù)總表) :基類1(參數(shù)表1),基類2(參數(shù)表2),…
內(nèi)嵌對象1(對象參數(shù)表1),…
派生類新增數(shù)據(jù)成員1(初值1),…{ 派生類中新增成員的初始化; }格式初始化列表派生類的構造函數(shù)與析構函數(shù)派生類構造函數(shù)說明:若派生類為單繼承,聲明中只有一個基類名;若派生類為多繼承,聲明中有多個基類名。單繼承舉例classB{public: B(intx,inty) :b1(x),b2(y) {}private:
intb1;protected:
intb2;};classD:publicB{public:
D(int
j,intk,intl,intm);protected:
intd1;private:
intd2;};D::D(int
j,int
k,int
l,intm) :B(j,k),
d1(l),d2(m){}Dobj(4,5,6,7);調(diào)用基類的構造函數(shù)來初始化從基類繼承的數(shù)據(jù)成員b1和b2派生類對象obj創(chuàng)建初始化過程示意圖Dobj(4,5,6,7);d2d1b2b1obj繼承部分新定義部分派生類成員D::D(int
j,int
k,int
l,intm) :B(j,k)
,
d1(l),d2(m){}=4=5=6=7B(intx,inty):b1(x),b2(y){}classB{public: B(intx,inty) :b1(x),b2(y) {}private:
intb1;protected:
intb2;};classD:publicB{public:
D(int
j,intk,intl,intm);protected:
intd1;private:
intd2;};D::D(int
j,int
k,int
l,intm) :B(j,k),
d1(l),d2(m){}Dobj(4,5,6,7);調(diào)用基類的構造函數(shù)來初始化從基類繼承的數(shù)據(jù)成員b1和b2B():b1(0),b2(0) {}B(),有必要寫出嗎?派生類的構造函數(shù)與析構函數(shù)派生類構造函數(shù)說明:若派生類為單繼承,聲明中只有一個基類名;若派生類為多繼承,聲明中有多個基類名。若基類使用默認構造函數(shù),聲明中可省略基類名(參數(shù)表)項;classB{public:
B():b1(0),b2(0) {}private:
intb1;protected:
intb2;};classD:publicB{public:D(intl,intm);protected:
intd1;private:
intd2;};D::D(intl,intm) :d1(l),d2(m){}Dobj(6,7);隱含調(diào)用基類缺省構造函數(shù)怎樣寫D類構造函數(shù)?;派生類的構造函數(shù)與析構函數(shù)派生類構造函數(shù)說明:若派生類為單繼承,聲明中只有一個基類名;若派生類為多繼承,聲明中有多個基類名。若基類使用默認構造函數(shù),聲明中可省略基類名(參數(shù)表)項;若此時派生類新增成員不需初始化,可以不定義派生類構造函數(shù)。classB{public:
B():b1(0),b2(0) {}private:
intb1;protected:
intb2;};classD:publicB{public:D(){}};Dobj;派生類無新增成員或者新增成員不需要初始化時,可以省略派生類構造函數(shù)含有內(nèi)嵌對象的類的構造函數(shù)舉例classB{public: B(intx,inty) :b1(x),b2(y) {}private:
intb1;protected:
intb2;};classD{public:protected:
Bd1;private:
intd2;};D::D(int
j,int
k,intl)
:d1(j,k),
d2(l){}Dobj(4,5,6);調(diào)用B類的構造函數(shù)來初始化內(nèi)嵌對象b1怎樣寫構造函數(shù)?D(int
j,intk,intl);派生類對象obj創(chuàng)建初始化過程示意圖Dobj(4,5,6);內(nèi)嵌對象d1D類成員D::D(int
j,int
k,intl) :d1(j,k)
,
d2(l){}d2d1.b2d1.b1obj=4=5=6B(intx,inty):b1(x),b2(y){}classB{public:
B() :b1(0) {}private:
intb1;};classD{public:protected:
Bd1;private:
intd2;};D::D(intj)
:d1(),
d2(l){}Dobj(4,5,6);調(diào)用B類的缺省構造函數(shù)來初始化內(nèi)嵌對象b1怎樣寫構造函數(shù)?D(intj);引入規(guī)則的舉例舉例classB{public:
B(intm):b1(m) {}protected:
intb1;};classD:publicB{public:
D(intm,intn)
{b1=m;d1=n;}protected:
intd1;};Dobj(6,7);思考:有問題嗎?引入規(guī)則的舉例舉例classB{public:
B(intm):b1(m) {}protected:
intb1;};classD{public:
D(intm,intn)
{d1.b1=m;d2=n;}protected:Bd1;
intd2;};Dobj(6,7);思考:有問題嗎?規(guī)則:能在初始化列表中初始化的成員,盡量在初始化列表中初始化。8.3派生類的構造函數(shù)與析構函數(shù)派生類構造函數(shù)(續(xù))派生類構造函數(shù)的執(zhí)行順序:按照基類被繼承時聲明的順序,調(diào)用基類構造函數(shù)。按照內(nèi)嵌對象在派生類中聲明的順序,調(diào)用內(nèi)嵌對象的構造函數(shù)。執(zhí)行派生類構造函數(shù)。classC{intmc;public: C(inti):mc(i) { cout<<"構造C" <<mc<<endl; }};classB{Cc1;Cc2;
int
mb;public:
B(inti,intj,intk);};intmain(){Bb(5,6,7);return0;}classA{protected:
intma;public:A(inti):ma(i){cout<<"構造A"<<endl;}};B::B(inti,intj,intk) :c1(i),c2(j),mb(k){
cout<<"構造B"<<endl;}:publicABb(5,6,7,8);B(inti,intj,intk,intl);B::B(inti,intj,intk,intl)c2(j),c1(i),:A(i),c1(j),c2(k),mb(l)初始化內(nèi)嵌對象時構造函數(shù)的調(diào)用與聲明順序一致,而與初始化列表中的順序無關classC{protected:
intmc;public: C(inti):c(i) { cout<<"構造C" <<mc<<endl; }};classB:publicA,publicC{int
mb;public:
B(inti,intj,intk);};intmain(){Bb(5,6,7);return0;}classA{protected:
intma;public:A(inti):ma(i){cout<<"構造A"<<endl;}};B::B(inti,intj,intk) :A(i),C(j),mb(k){
cout<<"構造B"<<endl;}
C(j),A(i),基類構造函數(shù)的調(diào)用與聲明順序一致,而與初始化列表中的順序無關
派生類的構造函數(shù)與析構函數(shù)派生類析構函數(shù)派生類與基類的析構函數(shù)彼此獨立,只作各自對象消亡前的善后工作。派生類析構函數(shù)的執(zhí)行順序:執(zhí)行派生類析構函數(shù)。按照內(nèi)嵌對象在派生類中聲明的相反順序,調(diào)用內(nèi)嵌對象的析構函數(shù)。按照基類被繼承時聲明的相反順序,調(diào)用基類析構函數(shù)。編程舉例:example8_3My8_1Question:為Person類和Student類添加構造函數(shù),可以初始化Person類和Student類對象。classPerson{
stringm_sName;
int
m_iAge;public:
int
GetAge()const;voidSet(stringname,intage); voidShow()const;};classStudent:publicPerson{ int
m_iNumber;public:
int
GetNumber()const;voidSetStudent(stringname,intage,intnumber); voidShowStudent()const;};protected:ClassPerson{……public:
Person(stringname,intage);};Person::Person(stringname,intage):m_sName(name),m_iAge(age){}ClassStudent{……public:Student(stringname,intage,intnumber);};Student::Student(stringname,intage,intnumber):Person(name,age),m_iNumber(number){}練習正方形:中心點坐標:(x,y),一頂點坐標:(x1,y1)面積:2*((x-x1)*(x-x1)+(y-y1)*(y-y1));聲明一個Shape(形狀)基類,它有兩個派生類:Circle(圓)和Square(正方形),要求:(1)根據(jù)給出的圓心坐標和半徑計算圓的面積;(2)根據(jù)給出的正方形中心坐標和一個頂點坐標計算正方形的面積。ShapeCircleSquare//shape.h的內(nèi)容classShape{protected: doublem_dX;//中心點x坐標
doublem_dY;//中心點y坐標public: Shape(doublex,doubley) :m_dX(x),m_dY(y) {} doubleGetX()const{returnm_dX;} doubleGetY()const{returnm_dY;} voidSetX(intx){m_dX=x;} voidSetY(inty){m_dY=y;}};//circle.h的內(nèi)容#include"shape.h"classCircle:publicShape{ doublem_dR;public: Circle(doublex,doubley,doubler) :Shape(x,y),m_dR(r) {} doubleGetArea()const {return3.14*m_dR*m_dR;}};//square.h的內(nèi)容#include"shape.h"classSquare:publicShape{ doublem_dX1; doublem_dY1;public: Square(doublex,doubley, doublex1,doubley1) :Shape(x,y),m_dX1(x1),m_dY1(y1) {} doubleGetArea()const;};//square.cpp的內(nèi)容#include"square.h"doubleSquare::GetArea()const{ return2*((m_dX-m_dX1)*(m_dX-m_dX1)+(m_dY-m_dY1)*(m_dY-m_dY1));}//main.cpp的內(nèi)容#include"circle.h"#include<iostream>usingnamespacestd;intmain(){ Circlec1(1,1,10);
cout<<c1.GetArea()<<endl; return0;}shape.h文件的內(nèi)容classShape{//…};circle.h文件的內(nèi)容#include"shape.h"classCircle :publicShape{//…};square.h文件的內(nèi)容#include"shape.h"classSquare :publicShape{//…};main.cpp文件
#include"circle.h"
#include"square.h"
intmain() { //用到了Circle類
//用到了Square類
return0;
}#include"shape.h"classCircle :publicShape{};#include"shape.h"classSquare :publicShape{};Shape.h文件被包含2次,怎么辦?多文件程序Question:
Shape.h文件被包含2次,怎么辦?Answer:預處理命令條件編譯條件編譯條件編譯命令是用來定義某些編譯內(nèi)容要在一定條件下才參與編譯的,否則不參與編譯。格式一:
#ifdef<標識符><程序段1>#else<程序段2>
#endif功能:當<標識符>被定義過,則<程序段1>參與編譯,否則<程序段2>參與編譯。
#ifdef<標識符>或<程序段1>
#endif條件編譯格式二:
#ifndef<標識符><程序段1>#else<程序段2>
#endif功能:當<標識符>被未定義過,則<程序段1>參與編譯,否則<程序段2>參與編譯。
#ifndef<標識符>或<程序段1>
#endif多文件程序#include<iostream>usingnamespacestd;intmain(){
cout<<"YYYYYYYYY"<<endl; #ifndefA
cout<<"XXXXXXXXX"<<endl;#endifreturn0;}#defineA參與編譯,形成目標代碼不參與編譯,不形成目標代碼條件編譯格式三:#if<條件1><程序段1>#elif<條件2><程序段2>……#elif<條件n><程序段n>#else<缺省程序段>
#endif例:#include<iostream>usingnamespacestd;#defineA10voidmain(){#if(A>0)
cout<<"a>0"<<endl;#elif(A<0)
cout<<"a<0"<<endl;#else
cout<<"a==0"<<endl;#endif}與c++的if語句的用法很相似,但有根本區(qū)別:If語句控制著某些語句是否執(zhí)行,而#if指令控制著某個程序段是否被編譯。多文件程序//test.h的內(nèi)容
classTest {inta; public: Test(intn):a(n) {} };//main.cpp的內(nèi)容
#include"test.h"
intmain(){ Testt(10); return0;} #include"test.h"多文件程序//main.cpp的內(nèi)容
#include"test.h" #include"test.h"
intmain() { Testt(10); return0; } classTest{ inta;public: Test(intn):a(n) {}};classTest{ inta;public: Test(intn):a(n) {}};intmain(){ Testt(10); return0;}預編譯多文件程序//test.h的內(nèi)容
#ifndefTEST_H#defineTEST_H classTest {inta; public: Test(intn):a(n) {} }; #endif//main.cpp的內(nèi)容
#include"test.h"#include"test.h"
intmain(){ Testt(10); return0;} 多文件程序main.cpp的內(nèi)容
#include"test.h" #include"test.h"
intmain() { Testt(10); return0; } #ifndefTEST_H#defineTEST_HclassTest{ inta;public: Test(intn):a(n) {}};#endif#ifndefTEST_H#defineTEST_HclassTest{ inta;public: Test(intn):a(n) {}};#endif………多文件程序任何一個頭文件都應該避免重復包含,避免重復包含的辦法如下:(對于頭文件abc.h)在頭文件的開頭加上
#ifndefABC_H#defineABC_H在頭文件的最后加上
#endifReturnquestionshape.h文件的內(nèi)容classShape{//…};circle.h文件的內(nèi)容#include"shape.h"classCircle :publicShape{//…};square.h文件的內(nèi)容#include"shape.h"classSquare :publicShape{//…};main.cpp文件
#include"circle.h"
#include"square.h"
intmain() { //用到了Circle類
//用到了Square類
return0;
}#include"shape.h"classCircle :publicShape{};#include"shape.h"classSquare :publicShape{};Shape.h文件被包含2次,怎么辦?條件編譯開發(fā)C++程序的步驟開發(fā)C++程序的步驟建模編程連接調(diào)試運行
C++程序的編譯過程分為預處理和正式編譯兩個步驟。在編譯C++程序時,編譯系統(tǒng)中的預處理模塊首先根據(jù)預處理命令對源程序進行適當?shù)募庸?,然后再正式編譯。編譯階段形成擴展名為.obj二進制目標文件。編譯注意:編譯預處理對宏、包含指令、條件編譯指令等進行處理詞法語法分析將源代碼翻譯成中間代碼(一般是匯編)優(yōu)化代碼將中間代碼翻譯成機器語言(目標文件),Ctrl+F7開發(fā)C++程序的步驟建模編譯編程調(diào)試運行連接階段形成擴展名為.exe二進制可執(zhí)行文件連接開發(fā)C++程序的步驟建模編譯編程調(diào)試運行連接開發(fā)C++程序的步驟建模編譯編程連接運行調(diào)試Ctrl+F5輸入、編譯、調(diào)試和運行一個C++程序C++程序a.hb.h……a.cppb.cppc.cpp…………a.cppb.cppc.cpp……預處理正式編譯a.objb.objc.obj……連接其他obj文件.exe文件引入classPerson{protected:
stringm_sName;
int
m_iAge;public:Person(conststringname,intage);
int
GetAge()const; voidShow()const;};//實現(xiàn)省略引入classStudent:publicPerson{int
m_iNumber;public:Student(conststringname,intage,intnumber);
int
GetNumber()const;voidShow()const;};//實現(xiàn)省略引入classTeacher:publicPerson{ stringm_sClass;public:Teacher(conststringname,intage,conststringsc);
int
GetNumber()const;voidShow()const;};//實現(xiàn)省略
引入Question:
定義函數(shù),實現(xiàn)如下功能:顯示Person類、Student類和Teacher類對象的年齡。voidShowAge(obj){
cout<<obj.GetAge()<<endl;}Answer:
1.重載ShowAge函數(shù)。//缺點?
2.?什么類型?4.7基類與派生類對象的關系基類與派生類之間的轉換回顧:當一個類擁有另一個類的所有屬性和行為時,就稱這兩個類之間具有繼承關系。繼承是一個具體化、特殊化的過程。personTeacherStudent繼承體現(xiàn)了“isa”的關系。基類與派生類之間的轉換在任何需要基類對象的地方都可以用公有派生類的對象來代替,這條規(guī)則稱賦值兼容規(guī)則。派生類的對象可以給基類對象賦值派生類的對象可以初始化基類的引用基類的指針也可以指向派生類對象不常用常用,多態(tài)的前提常用,多態(tài)的前提概念(補充)繼承方式表現(xiàn)前提:公有繼承問題總結補充派生類對象對基類對象賦值
1.派生類的對象可以給基類的對象賦值基類數(shù)據(jù)成員基類成員函數(shù)
基類基類數(shù)據(jù)成員基類成員函數(shù)派生類新增數(shù)據(jù)成員新增成員函數(shù)賦值時此部分舍去不用Question:反過來可以嗎?Answer:不可以!??classA{ intma;public: A(inti):ma(i) {}
int
GetA()const {returnma;}};classB:publicA{int
mb;public:B(inti,intj):A(i),mb(j){}
int
GetB()const{returnmb;}};intmain(){AobjA(3);BobjB(7,8);
objA=objB;
cout<<objA.GetA();
cout<<objA.GetB(); return0;}//Error!注意:賦值后不能企圖通過基類對象訪問派生類成員。objAma=3objBma=7mb=8GetA()GetB()ma=7派生類對象初始化基類引用2.派生類的對象可以初始化基類的引用基類數(shù)據(jù)成員基類成員函數(shù)objB派生類數(shù)據(jù)成員派生類成員函數(shù)rABobjB;A&rA=objB;注意:rA只是對派生類對象objB中的基類隱含對象的引用AobjA;B&rB=objA;反之不可以!objArB?classA{ intma;public: A(inti):ma(i) {}
int
GetA()const {returnma;}};classB:publicA{ int
mb;public: B(inti,intj) :A(i),mb(j) {}
int
GetB()const {returnmb;}};intmain(){ BobjB(7,8);
A&r=objB;
cout<<r.GetA();
cout<<r.GetB();
return0;}//Error!objBma=7mb=8GetA()GetB()r注意:通過這種引用只能訪問派生類對象中的由基類繼承來的成員,不能訪問派生類中的新增成員。classA{ intma;public: A(inti):ma(i) {}
A(constA&a):ma(a.ma) {}
int
GetA()const {returnma;}};classB:publicA{ int
mb;public:
B(inti,intj) :A(i),mb(j) {}
int
GetB()const {returnmb;}};intmain(){ BobjB(7,8);
AobjA(objB );
cout<<objA.GetA(); return0;}指向基類的指針指向派生類對象3.可以將派生類的對象的地址賦給其基類的指針變量通過這個指針訪問派生類中由基類繼承來的成員,不能訪問派生類中的新增成員。反過來不行。classA{ intma;public: A(inti):ma(i) {}
int
GetA()const {returnma;}};classB:publicA{int
mb;public:
B(inti,intj):A(i),mb(j){}
int
GetB()const{returnmb;}};intmain(){ BobjB(7,8);
cout<<objB.GetA()<<objB.GetB();
A*p=&objB;
cout<<p->GetA();
cout<<p->GetB();
return0;}//Error!概念(補充)概念(補充)對象的靜態(tài)類型指聲明的存在于程序代碼文本中的類型。對象的動態(tài)類型由它當前所指的對象的類型決定的。舉例:A*p=&objB; //p的靜態(tài)類型為:A* //p的動態(tài)類型為:B*
非虛函數(shù)是靜態(tài)綁定的,即,非虛函數(shù)的調(diào)用取決于對象的靜態(tài)類型。
注意如:A*p=&objB;p->GetA();p->GetB();//Error!classA{ intma;public: A(inti):ma(i) {}
int
GetA()const {returnma;}};classB:publicA
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年軟件許可使用合同的軟件范圍和許可期限
- 2024年物業(yè)清潔合同:保持環(huán)境共創(chuàng)綠色家園
- 品質生活從時尚選擇開始
- 立秋營銷新篇章
- 2024私房舊房交易糾紛調(diào)解服務合同3篇
- 媒體新篇章模板
- 揭秘全球旅游新趨勢
- 大宗商品貨款質押合同(2篇)
- 《煤礦職業(yè)病危害防治》培訓課件2025
- 2024陶瓷杯團購采購合同附帶市場調(diào)研與產(chǎn)品改進服務3篇
- 山地光伏安全文明施工方案
- 中醫(yī)醫(yī)院運營方案
- 公務員報考指南
- 烏頭堿中毒急診科培訓課件-
- 貴州茅臺2023審計報告
- 高速鐵路沉降觀測與評估
- 家長要求學校換老師的申請書
- IT項目周報模板
- 鐵路工程主要建材碳排放因子、常用施工機械臺班能源用量、類運輸方式、能源碳排放因子、不同植栽方式綠化固碳量
- 藥品養(yǎng)護記錄表
- 食堂服務外包投標方案(技術標)
評論
0/150
提交評論