




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
C++語言是C的擴充擴充C語言C++語言擴充的目的:支持面向?qū)ο蟪绦蛟O計擴充的功能:類定義消息傳遞(類似函數(shù)調(diào)用)繼承、虛函數(shù)第二章類和對象C++語言是C的擴充第二章類和對象對象與封裝對象相對獨立的實體具有表示其狀態(tài)、特征的屬性具有表示其行為、功能的操作封裝性:只有自身操作可訪問對象屬性面向?qū)ο蠓椒▽⒎治觥⒃O計的系統(tǒng)和程序都抽象為對象組成的模型面向?qū)ο蟪绦蛟O計運行中程序?qū)嵗?若干對象實例+交互控制程序=若干對象類(用于描述各種對象)對象類=程序模塊C++程序=主函數(shù)(main)+若干類定義對象與封裝對象相對獨立的實體類C++的類是把各種不同類型的數(shù)據(jù)(稱為數(shù)據(jù)成員)和對數(shù)據(jù)的操作(成員函數(shù))組織在一起而形成的用戶自定義的數(shù)據(jù)類型。C++中,類定義包括類說明和類實現(xiàn)兩大部分。說明部分提供了對該類所有數(shù)據(jù)成員和成員函數(shù)的描述,而實現(xiàn)部分提供了所有成員函數(shù)的實現(xiàn)代碼。類C++的類是把各種不同類型的數(shù)據(jù)(稱為數(shù)據(jù)成員)和對數(shù)據(jù)的類的定義***.h
class
類名{數(shù)據(jù)成員的說明public:
方法成員的說明};類的定義***.h說明:類名由用戶自己定,一般首字母大寫默認是private,只有類中的成員函數(shù)才能訪問注意:類定義的末尾有一分號注意:不能在類定義中對數(shù)據(jù)成員進行初始化
classLocation{intx=25,y;//ERROR};說明:classDate{intyear,month,day;public:
Date(inty,intm,intd); voidsetYear(inty); voidsetMonth(intm); voidsetDay(intd); intgetYear();intgetMonth();intgetDay();};//date.h類的定義classDate//date.h類的定義成員函數(shù)的定義1、將成員函數(shù)的定義直接寫在類中適合于成員函數(shù)規(guī)模較小的情況(內(nèi)聯(lián)函數(shù))2、在類的定義體中只寫出成員函數(shù)的原型說明,而成員函數(shù)的定義之后再寫通常將類的定義寫在一個頭文件(.h文件)中,成員函數(shù)的定義寫在一個程序文件(.cpp文件)中一般形式:返回類型類名::成員函數(shù)名(參數(shù)說明){類體}成員函數(shù)的定義1、將成員函數(shù)的定義直接寫在類中classDate{intyear,month,day;public:
Date(inty,intm,intd); voidsetYear(inty); voidsetMonth(intm); voidsetDay(intd); intgetYear();intgetMonth();intgetDay(){returnday;}
//內(nèi)聯(lián)函數(shù)};classDate//date.cpp實現(xiàn)部分#include"date.h"
Date::Date(inty,intm,intd){ year=y;month=m;day=d;}intDate::getYear(){ returnyear;}//date.cpp實現(xiàn)部分intDate::getMonth(){ returnmonth;}intDate::getDay(){ returnday;}intDate::getMonth(){voidDate::setYear(inty){ year=y;}voidDate::setMonth(intm){ month=m;}voidDate::setDay(intd){ day=d;}voidDate::setYear(inty){//exam.cppDate類的測試程序#include<iostream.h>#include"date.h"voidmain(){
Datek(2000,12,1); cout<<k.getMonth()<<endl;}//exam.cppDate類的測試程序?qū)ο髣?chuàng)建時,為數(shù)據(jù)成員分配存儲空間調(diào)用類的構(gòu)造函數(shù)對象生命周期結(jié)束時,調(diào)用類的析構(gòu)函數(shù)對象創(chuàng)建時,為數(shù)據(jù)成員分配存儲空間構(gòu)造函數(shù)是一種特殊的成員函數(shù),函數(shù)名與類名相同當定義該類的對象時,構(gòu)造函數(shù)將被自動調(diào)用以實現(xiàn)對該對象的初始化構(gòu)造函數(shù)不能有返回值,因而不能指定包括void在內(nèi)的任何返回值類型構(gòu)造函數(shù)既可定義帶參,也可義不帶參一個類可定義多個構(gòu)造函數(shù),也可以不定義構(gòu)造函數(shù),沒定義構(gòu)造函數(shù)時,則自動建立一個空的不帶參構(gòu)造函數(shù)(默認構(gòu)造函數(shù))構(gòu)造函數(shù)是一種特殊的成員函數(shù),函數(shù)名與類名相同析構(gòu)函數(shù)函數(shù)名與類名相同,前有~沒有參數(shù),沒有返回值在類對象生命期結(jié)束時,系統(tǒng)自動調(diào)用一個類只可定義一個析構(gòu)函數(shù),也可以不定義如果在類的對象中分配有動態(tài)內(nèi)存(如:用new申請分配的內(nèi)容)時,就必須為該類提供適當?shù)奈鰳?gòu)函數(shù),完成清理工作析構(gòu)函數(shù)函數(shù)名與類名相同,前有~this指針誰的成員?Datec1,c2;intDate::getYear(){ returnyear;//c1?C2?}this指針誰的成員?this指針C++的非靜態(tài)成員函數(shù)有一個隱含參數(shù)X*constthisintDate::getYear(Date*constthis){ returnthis->year;}c1.getYear(&c1);this指針C++的非靜態(tài)成員函數(shù)有一個隱含參數(shù)intDa例:有理數(shù)類的定義#include<iostream.h>classCRation{ longn; //分子
longd; //分母public: CRation(long,long);//構(gòu)造
voidPrint(); //輸出
voidGcd(); //約分};例:有理數(shù)類的定義CRation::CRation(longn,longd){ //對象創(chuàng)建時被調(diào)用
this->n=n; //this是指向當前對象的指針
this->d=d;}voidCRation::Print(void){ cout<<n<<"/"<<d<<endl;}CRation::CRation(longn,longvoidCRation::Gcd() { intx=n,y=d,t; if(x<y) {t=x;x=y;y=t;} t=x%y;while(t!=0){ x=y;y=t;t=x%y; } n/=y;d/=y; }《C類和對象》課件main() {CRationr(18,27);//分配空間,調(diào)構(gòu)造函數(shù)r.Print(); //輸出r.Gcd(); //約分r.Print(); }main() 例:動態(tài)整數(shù)數(shù)組類作為對象的數(shù)組唯一標識的實體封裝數(shù)組元素、元素個數(shù)等信息責任功能按照下標的訪問數(shù)組大小可變可獲取元素個數(shù)#include<iostream.h>#include<string.h>classArray{ int*pElems; intsize; //個數(shù)public: Array(intn); //構(gòu)造 ~Array(void);//析構(gòu)
voidSetAt(inti,intv); intGetAt(inti); //存取
intGetSize(void);}; 例:動態(tài)整數(shù)數(shù)組類作為對象的數(shù)組#include<iost類設計要點獨立性表示獨立的實體以屬性表示其特征以行為表示其擔負的責任(功能、服務)封裝性不開放屬性提供足夠的方法,支持各種用途隱蔽內(nèi)部數(shù)據(jù)結(jié)構(gòu)隱蔽方法的內(nèi)部算法復用性適用性強、功能豐富類設計要點獨立性方法的實現(xiàn)(1/2)Array::Array(intn) { //構(gòu)造n元素的數(shù)組
pElems=newint[n]; //動態(tài)生成
size=n;}Array::~Array(void) { //撤消前被自動調(diào)用
delete[]pElems; //釋放空間}intArray::GetSize(void) { returnsize; //獲得數(shù)組大小}方法的實現(xiàn)(1/2)Array::Array(intn方法的實現(xiàn)(2/2)voidArray::SetAt(inti,intv){ //按下標i賦值v if(i>=size) { //超過范圍
int*p=newint[size+5];//開辟空間,復制數(shù)據(jù)
memcpy(p,pElems,size*sizeof(int)); size+=5; delete[]pElems; //釋放原數(shù)組空間
pElems=p; //保存首地址 } *(pElems+i)=v; //賦值}intArray::GetAt(inti) //按下標i取元素數(shù)據(jù){
returni<size?*(pElems+i):0;} 方法的實現(xiàn)(2/2)voidArray::SetAt(動態(tài)數(shù)組的使用voidmain() { intn; Arrayx(10); //數(shù)組對象實例變量
for(inti=0;i<20;i++) { cout<<"Input:"; cin >>n; x.SetAt(i,n); } for(i=0;i<x.GetSize();i++) cout << x.GetAt(i)<<"";}動態(tài)數(shù)組的使用voidmain() 程序分析對象類=數(shù)據(jù)結(jié)構(gòu)+相關函數(shù)屬性=結(jié)構(gòu)分量方法=作用于結(jié)構(gòu)的函數(shù)對象實例變量靜態(tài)構(gòu)造局部變量、全局變量動態(tài)構(gòu)造new類名(參數(shù)表)函數(shù)定義標識所屬的類可以直接訪問參數(shù)和本類的數(shù)據(jù)成員函數(shù)調(diào)用通過對象實例調(diào)用其方法程序分析對象類=數(shù)據(jù)結(jié)構(gòu)+相關函數(shù)消息傳遞對象方法的激活使用者向?qū)ο髮嵗l(fā)消息對象用方法函數(shù)響應消息消息的組成消息名函數(shù)名消息屬性參數(shù)值的列表核心點使用者僅關心消息的組成對象決定哪個方法負責響應消息傳遞對象方法的激活消息傳遞消息響應不同類可以有同名方法函數(shù)同類中可以有原型不同的方法消息響應方法的選擇消息名=方法名接收消息的對象(對象類)匹配函數(shù)原型(參數(shù)個數(shù)、參數(shù)類型)消息傳遞消息響應對象成員一個類的對象作為另一個類的數(shù)據(jù)成員classX{
類名1成員名1類名2成員名2…...
};構(gòu)造函數(shù)
X::X(參數(shù)表0):成員1(參數(shù)表1),成員2(參數(shù)表2){…...}
對象成員一個類的對象作為另一個類的數(shù)據(jù)成員建立X類對象時,先調(diào)對象成員的構(gòu)造函數(shù),然后才執(zhí)行X類的構(gòu)造函數(shù)對象成員構(gòu)造函數(shù)的調(diào)用順序取決于這些對象成員在類中的說明順序析構(gòu)函數(shù)的調(diào)用順序與構(gòu)造函數(shù)相反建立X類對象時,先調(diào)對象成員的構(gòu)造函數(shù),然后才執(zhí)行X類的構(gòu)造#include"Date.h"classStudent_Info{ intNo; charName[20];charSex;
DateBirthday;
public:Student_Info(intn,char*a,chars,inty,intm,intd);Student_Info();intGetNo();char*GetName();charGetSex();……};#include"Date.h"#include"Student.h"Student_Info::Student_Info(intn,char*a,chars,inty,intm,intd):Birthday(y,m,d){No=n; strcpy(Name,a);Sex=s;}Student_Info::Student_Info():Birthday(2000,1,1){No=0;strcpy(Name,"");Sex='m';}#include"Student.h"程序結(jié)構(gòu)一般分為三個文件:1)將類的說明作為頭文件.h2)將類的成員函數(shù)的實現(xiàn)放一個文件.cpp3)對類的使用放一個文件,包括main.cpp程序結(jié)構(gòu)一般分為三個文件:作業(yè):定義日期類定義描述書的類,包括書名、價格、出版日期等作業(yè):第三章繼承現(xiàn)實世界中的一般特殊關系人學生人教師類的繼承學生類繼承人類教師類繼承人類派生類:描述特殊的屬性和行為基類:描述一般的屬性和行為第三章繼承現(xiàn)實世界中的一般特殊關系C++語言對繼承的支持class派生類:public基類{ … // 特殊屬性 … // 特殊方法 };派生類繼承了基類的屬性和方法支持軟件模塊的復用復用了基類的數(shù)據(jù)結(jié)構(gòu)和成員函數(shù)C++語言對繼承的支持class派生類:publi【例】分別定義一個描述圓的類Circle和描述一個圓柱體的類Cylinder。【例】分別定義一個描述圓的類Circle和描述一個圓柱體的類#ifndefCircle_H#defineCircle_HclassCircle//定義圓類{
protected:doubleradius;public:Circle(doubler){radius=r;}voidsetradius(doubler){radius=r;}doublegetradius(){returnradius;}doublearea(){return3.14*radius*radius;}};#endif#ifndefCircle_H#include"Circle.h"classCylinder:publicCircle//定義圓柱體類{
doubleheight;public:Cylinder(doubler,doubleh);
voidsetheight(doubleh);
doublegetheight();
doublearea();//重新定義area()函數(shù)};#include"Circle.h"#include"Cylinder.h"Cylinder::Cylinder(doubler,doubleh):Circle(r)
{height=h;}voidCylinder::setheight(doubleh){height=h;}doubleCylinder::getheight(){returnheight;}doubleCylinder::area()//重新定義area()函數(shù){return2*Circle::area()+2*3.14*radius*height;}#include"Cylinder.h"#include<iostream.h>#include"Cylinder.h"#include"Circle.h"voidmain(){Circles1(10);Cylinders2(2,5);cout<<"圓柱體表面積:"<<s2.area()<<endl;
cout<<"圓的面積是:"<<s1.area()<<endl;}#include<iostream.h>在創(chuàng)建派生類的對象時,由于派生類的對象包含了基類的數(shù)據(jù)成員,因此派生類的構(gòu)造函數(shù)除初始化其自身定義的數(shù)據(jù)成員外,還必須對基類中的數(shù)據(jù)成員進行初始化,也就是說,派生類的構(gòu)造函數(shù)要負責調(diào)用基類的構(gòu)造函數(shù)。派生類的構(gòu)造函數(shù)的定義格式如下:派生類名::派生類構(gòu)造函數(shù)名(參數(shù)表):基類構(gòu)造函數(shù)名(參數(shù)表){……}在創(chuàng)建派生類的對象時,由于派生類的對象包含了基類的數(shù)據(jù)成員,基類的對象只能調(diào)用基類的成員函數(shù),不能調(diào)用派生類的成員函數(shù)在定義派生類的對象時,系統(tǒng)首先執(zhí)行基類的構(gòu)造函數(shù),然后執(zhí)行派生類的構(gòu)造函數(shù)。而系統(tǒng)執(zhí)行析構(gòu)函數(shù)的順序恰恰相反,即先執(zhí)行派生類的析構(gòu)函數(shù),再執(zhí)行基類的析構(gòu)函數(shù)若在基類中沒有定義任何構(gòu)造函數(shù),這時在派生類的構(gòu)造函數(shù)的定義中可以省略對基類構(gòu)造函數(shù)的調(diào)用,此時系統(tǒng)將去調(diào)用基類的默認構(gòu)造函數(shù)。
基類的對象只能調(diào)用基類的成員函數(shù),不能調(diào)用派生類的成員函數(shù)多繼承定義多繼承類的方式:class派生類名:訪問方式基類1,訪問方式基類2……{……};其中:訪問方式同單繼承多繼承下派生類的構(gòu)造函數(shù)必須同時負責所有基類構(gòu)造函數(shù)的調(diào)用在多繼承下,派生類構(gòu)造函數(shù)的定義格式:派生類構(gòu)造函數(shù)名(參數(shù)表):基類名1(參數(shù)表1),……{……}多繼承定義多繼承類的方式:在多繼承下,系統(tǒng)首先執(zhí)行各基類的構(gòu)造函數(shù),然后再執(zhí)行派生類的構(gòu)造函數(shù),處于同一層次的各基類構(gòu)造函數(shù)的執(zhí)行順序與聲明派生類時所指定的各基類順序一致,而與派生類的構(gòu)造函數(shù)定義中所調(diào)用基類構(gòu)造函數(shù)的順序無關。在多繼承下,系統(tǒng)首先執(zhí)行各基類的構(gòu)造函數(shù),然后再執(zhí)行派生類的第四章多態(tài)性與虛函數(shù)多態(tài)性不同事物以不同方式響應同一消息演出發(fā)消息“暫?!苯o 比賽會議產(chǎn)生不同的消息響應消息響應取決于接受消息的對象,而不是發(fā)送者第四章多態(tài)性與虛函數(shù)多態(tài)性【例】#include<iostream.h>classA{inta;public:A(inti=0){a=i;}voidprint();};voidA::print(){cout<<"InclassA,print()iscalled."<<endl;}【例】classB:publicA
{intb;public:B(intj=-1){b=j;}
voidprint();};voidB::print(){cout<<"InclassB,print()iscalled."<<endl;}classB:publicAvoidmain(){Aa,*pa;Bb,*pb;pa=&a;pa->print();pb=&b;pb->print();
pa=&b;//基類指針可以指向派生類對象
pa->print();}voidmain()《C類和對象》課件voidcommfun(A&aref){aref.print();}voidmain(){Aa;a.print();commfun(a);//以基類A的對象a作實參Bb;b.print();commfun(b);//以派生類B的對象b作實參}voidcommfun(A&aref)《C類和對象》課件分析:在派生類B中繼承了基類A的成員函數(shù)print(),又定義了一個同名的print()函數(shù)。這種改變在靜態(tài)聯(lián)編的基礎上編譯器并不知道。必須通知編譯器這種可能的改變,即需要進行動態(tài)聯(lián)編。其方法就是在基類中將可能發(fā)生改變的成員函數(shù)聲明為虛函數(shù)。分析:在派生類B中繼承了基類A的成員函數(shù)print(),又定虛函數(shù)聲明虛函數(shù)的方法是在基類中的成員函數(shù)原型前加上關鍵字virtual。其格式如下:
class類名{……
virtual
類型函數(shù)名(參數(shù)表);……};虛函數(shù)聲明虛函數(shù)的方法是在基類中的成員函數(shù)原型前加上關鍵字v當一個類的成員函數(shù)說明為虛函數(shù)后,在該類的派生類中定義與其基類虛函數(shù)原型相同的函數(shù)。這時,當用基類指針指向這些派生類對象時,系統(tǒng)會在程序運行中根據(jù)所指對象的不同,自動選擇派生類中的同名函數(shù)來代替基類中的虛函數(shù)。當一個類的成員函數(shù)說明為虛函數(shù)后,在該類的派生類中定義與其基虛函數(shù)在派生類中重新定義時,必須與基類中的函數(shù)原型完全相同,包括函數(shù)名、返回類型、參數(shù)個數(shù)和參數(shù)類型的順序。這時無論在派生類的相應成員函數(shù)前是否加上關鍵字virtual,都將視其為虛函數(shù)。如果函數(shù)原型不同,只是函數(shù)名相同,C++將視其為一般的函數(shù)重載,而不是虛函數(shù)。虛函數(shù)在派生類中重新定義時,必須與基類中的函數(shù)原型完全相同,#include<iostream.h>classP{public:
virtualvoidprint(){cout<<"ParentClass"<<endl;}};classA:publicP{public:
virtualvoidprint(){cout<<"SubClass1"<<endl;}};classB:publicP{public:
virtualvoidprint(){cout<<"SubClass2"<<endl;}};#include<iostream.h>voidmain(){Aobj1;Bobj2;P*s1; s1=&obj1;s1->print();s1=&obj2;s1->print();}通過指針voidmain()通過指針classA{public:
virtualvoidPrint(){cout<<"Parent"<<endl;}};classB:publicA{public: virtualvoidPrint(){cout<<"Subclass"<<endl;}};voidshow(A&a){ a.Print();}通過引用classA{通過引用voidmain(){Bb;show(b);}voidmain()純虛函數(shù)在基類中只聲明虛函數(shù)而不給出具體的函數(shù)定義體,將它的具體定義放在各派生類中,稱此虛函數(shù)為純虛函數(shù)。通過該基類的指針或引用就可以調(diào)用所有派生類的虛函數(shù),基類只是用于繼承,僅作為一個接口,具體功能在派生類中實現(xiàn)。形式:virtual類型函數(shù)名(參數(shù)表)=0;純虛函數(shù)在基類中只聲明虛函數(shù)而不給出具體的函數(shù)定義體,將它的抽象類若一個類至少有一個純虛函數(shù),就稱該類為抽象類。抽象類中可以有多個純虛函數(shù),也可以定義其他非純虛函數(shù)。抽象類若一個類至少有一個純虛函數(shù),就稱該類為抽象類。不能聲明抽象類的對象,但可以聲明指向抽象類的指針變量和引用變量。如果派生類中沒有重新定義基類中的純虛函數(shù),則在派生類中必須再將該虛函數(shù)聲明為純虛函數(shù)。從抽象類可以派生出具體或抽象類。引入抽象類的目的,主要是為了能將相關類組織在一個類繼承結(jié)構(gòu)中,并通過抽象類來為這些相關類提供統(tǒng)一的操作接口。不能聲明抽象類的對象,但可以聲明指向抽象類的指針變量和引用變【例】設計一個抽象類shape,它表示具有形狀的東西,體現(xiàn)了抽象的概念,在它下面可以派生出多種具體形狀,比如三角形、矩形。#include<iostream.h>classShape{protected:doublex,y;public:voidset(doublei,doublej){x=i;y=j;}virtualvoidarea()=0;//聲明純虛函數(shù)};【例】設計一個抽象類shape,它表示具有形狀的東西,體現(xiàn)classTriangle:publicShape{public:voidarea(){cout<<"三角形面積:"<<0.5*x*y<<endl;}};classRectangle:publicShape{public:voidarea(){cout<<"矩形面積:"<<x*y<<endl;}};classTriangle:publicShapevoidshowarea(Shape&s){ s.area();}voidmain(){Trianglet;Rectangler;t.set(2,10);showarea(t);r.set(5.1,10);showarea(r);}voidshowarea(Shape&s)《C類和對象》課件接口與復用程序模塊(構(gòu)件)軟件的組成部件軟件工程觀點:通過組裝構(gòu)件來開發(fā)軟件對象類作為程序模塊,程序模塊之間的交互手段:模塊接口模塊接口一組函數(shù)原型(方法)描述了如何訪問該模塊編程語言提供接口描述方法C++提供抽象類和純虛函數(shù)Java提供接口interface接口與復用程序模塊(構(gòu)件)用C++語言描述接口例:整數(shù)容器接口描述用于維護一組整數(shù)的程序模塊classIntContainer{public: virtualintGetNumber(void)=0; //獲得整數(shù)個數(shù)
virtualintGetAt(intidx)=0; //獲得第idx個元素
virtualvoidAdd(intval)=0; //添加元素};純虛函數(shù):自己不定義,要求派生類必須定義抽象類:僅作為基類,不能直接實例化對象接口無數(shù)據(jù)成員、僅提供純虛函數(shù)的抽象類用C++語言描述接口例:整數(shù)容器接口實現(xiàn)同一功能的兩個模塊classIntArray :publicIntContainer{ int *pData,size,used;public: IntArray(intsz);~IntArray(void); intGetNumber(); intGetAt(intidx); voidAdd(intval);};classIntList :publicIntContainer{ structNode{ intval; structNode*next; }*pHead;public: IntList(); intGetNumber(); intGetAt(intidx); voidAdd(intval);};實現(xiàn)同一功能的兩個模塊classIntArraycl兩個類的對比IntArray 實現(xiàn)動態(tài)數(shù)組pData 指向數(shù)組首元素地址size 數(shù)組大小used 整數(shù)的個數(shù)IntList 實現(xiàn)整數(shù)鏈表Node 結(jié)點的結(jié)構(gòu)pHead 鏈表首元素地址接口創(chuàng)建方法不同使用方法相同以不同的數(shù)據(jù)結(jié)構(gòu)、不同的算法提供相同的功能兩個類的對比IntArray 實現(xiàn)動態(tài)數(shù)組IntArray的實現(xiàn)IntArray::IntArray(intsz){ pData =newint[size=sz];//申請空間used=0;
}IntArray::~IntArray(void){ delete []pData; //釋放空間}intIntArray::GetNumber(void){ return used; //元素個數(shù)}intIntArray::GetAt(intidx){ if(idx>=used) return -1; //超界處理
return pData[idx];}IntArray的實現(xiàn)IntArray::IntArrayvoidIntArray::Add(intval){ if(used==size){ //擴大數(shù)組的尺寸(+8)
int*p =newint[size+8]; memcpy(p,pData,sizeof(int)*size); delete []pData; //釋放原空間
pData =p; //新的空間
size +=8; } pData[used++] =val; //添加元素}voidIntArray::Add(intval)IntList的實現(xiàn)IntList::IntList() {pHead=NULL;}intIntList::GetNumber(void){ intn=0; for(Node*p=pHead;p!=NULL;p=p->next) n++; //元素的計數(shù)
returnn;}intIntList::GetAt(intidx){ for(Node*p=pHead;p!=NULL;p=p->next) if(idx--==0) returnp->val; //找到指定元素
return-1;}IntList的實現(xiàn)IntList::IntList()voidIntList::Add(intval){ Node*p=newNode(); p->val =val; // 構(gòu)造新結(jié)點
p->next =NULL; if(pHead==NULL){ // 空表?
pHead=p; return; } for(Node*q=pHead;q->next!=NULL;q=q->next); q->next =p; // 加在表尾}voidIntList::Add(intval)intsum(IntContainer*pSet){ ints=0;
for(inti=0;i<pSet->GetNumber();i++) s +=pSet->GetAt(pSet);returns;} main(){ IntArrayar(10); IntListls; ar.Add(10);ar.Add(23);ar.Add(32); ls.Add(10);ls.Add(23);ls.Add(32); ints1=sum(&ar); ints2=sum(&ls);cout<<s1<<endl<<s2;} intsum(IntContainer*pSet)C++語言是C的擴充擴充C語言C++語言擴充的目的:支持面向?qū)ο蟪绦蛟O計擴充的功能:類定義消息傳遞(類似函數(shù)調(diào)用)繼承、虛函數(shù)第二章類和對象C++語言是C的擴充第二章類和對象對象與封裝對象相對獨立的實體具有表示其狀態(tài)、特征的屬性具有表示其行為、功能的操作封裝性:只有自身操作可訪問對象屬性面向?qū)ο蠓椒▽⒎治?、設計的系統(tǒng)和程序都抽象為對象組成的模型面向?qū)ο蟪绦蛟O計運行中程序?qū)嵗?若干對象實例+交互控制程序=若干對象類(用于描述各種對象)對象類=程序模塊C++程序=主函數(shù)(main)+若干類定義對象與封裝對象相對獨立的實體類C++的類是把各種不同類型的數(shù)據(jù)(稱為數(shù)據(jù)成員)和對數(shù)據(jù)的操作(成員函數(shù))組織在一起而形成的用戶自定義的數(shù)據(jù)類型。C++中,類定義包括類說明和類實現(xiàn)兩大部分。說明部分提供了對該類所有數(shù)據(jù)成員和成員函數(shù)的描述,而實現(xiàn)部分提供了所有成員函數(shù)的實現(xiàn)代碼。類C++的類是把各種不同類型的數(shù)據(jù)(稱為數(shù)據(jù)成員)和對數(shù)據(jù)的類的定義***.h
class
類名{數(shù)據(jù)成員的說明public:
方法成員的說明};類的定義***.h說明:類名由用戶自己定,一般首字母大寫默認是private,只有類中的成員函數(shù)才能訪問注意:類定義的末尾有一分號注意:不能在類定義中對數(shù)據(jù)成員進行初始化
classLocation{intx=25,y;//ERROR};說明:classDate{intyear,month,day;public:
Date(inty,intm,intd); voidsetYear(inty); voidsetMonth(intm); voidsetDay(intd); intgetYear();intgetMonth();intgetDay();};//date.h類的定義classDate//date.h類的定義成員函數(shù)的定義1、將成員函數(shù)的定義直接寫在類中適合于成員函數(shù)規(guī)模較小的情況(內(nèi)聯(lián)函數(shù))2、在類的定義體中只寫出成員函數(shù)的原型說明,而成員函數(shù)的定義之后再寫通常將類的定義寫在一個頭文件(.h文件)中,成員函數(shù)的定義寫在一個程序文件(.cpp文件)中一般形式:返回類型類名::成員函數(shù)名(參數(shù)說明){類體}成員函數(shù)的定義1、將成員函數(shù)的定義直接寫在類中classDate{intyear,month,day;public:
Date(inty,intm,intd); voidsetYear(inty); voidsetMonth(intm); voidsetDay(intd); intgetYear();intgetMonth();intgetDay(){returnday;}
//內(nèi)聯(lián)函數(shù)};classDate//date.cpp實現(xiàn)部分#include"date.h"
Date::Date(inty,intm,intd){ year=y;month=m;day=d;}intDate::getYear(){ returnyear;}//date.cpp實現(xiàn)部分intDate::getMonth(){ returnmonth;}intDate::getDay(){ returnday;}intDate::getMonth(){voidDate::setYear(inty){ year=y;}voidDate::setMonth(intm){ month=m;}voidDate::setDay(intd){ day=d;}voidDate::setYear(inty){//exam.cppDate類的測試程序#include<iostream.h>#include"date.h"voidmain(){
Datek(2000,12,1); cout<<k.getMonth()<<endl;}//exam.cppDate類的測試程序?qū)ο髣?chuàng)建時,為數(shù)據(jù)成員分配存儲空間調(diào)用類的構(gòu)造函數(shù)對象生命周期結(jié)束時,調(diào)用類的析構(gòu)函數(shù)對象創(chuàng)建時,為數(shù)據(jù)成員分配存儲空間構(gòu)造函數(shù)是一種特殊的成員函數(shù),函數(shù)名與類名相同當定義該類的對象時,構(gòu)造函數(shù)將被自動調(diào)用以實現(xiàn)對該對象的初始化構(gòu)造函數(shù)不能有返回值,因而不能指定包括void在內(nèi)的任何返回值類型構(gòu)造函數(shù)既可定義帶參,也可義不帶參一個類可定義多個構(gòu)造函數(shù),也可以不定義構(gòu)造函數(shù),沒定義構(gòu)造函數(shù)時,則自動建立一個空的不帶參構(gòu)造函數(shù)(默認構(gòu)造函數(shù))構(gòu)造函數(shù)是一種特殊的成員函數(shù),函數(shù)名與類名相同析構(gòu)函數(shù)函數(shù)名與類名相同,前有~沒有參數(shù),沒有返回值在類對象生命期結(jié)束時,系統(tǒng)自動調(diào)用一個類只可定義一個析構(gòu)函數(shù),也可以不定義如果在類的對象中分配有動態(tài)內(nèi)存(如:用new申請分配的內(nèi)容)時,就必須為該類提供適當?shù)奈鰳?gòu)函數(shù),完成清理工作析構(gòu)函數(shù)函數(shù)名與類名相同,前有~this指針誰的成員?Datec1,c2;intDate::getYear(){ returnyear;//c1?C2?}this指針誰的成員?this指針C++的非靜態(tài)成員函數(shù)有一個隱含參數(shù)X*constthisintDate::getYear(Date*constthis){ returnthis->year;}c1.getYear(&c1);this指針C++的非靜態(tài)成員函數(shù)有一個隱含參數(shù)intDa例:有理數(shù)類的定義#include<iostream.h>classCRation{ longn; //分子
longd; //分母public: CRation(long,long);//構(gòu)造
voidPrint(); //輸出
voidGcd(); //約分};例:有理數(shù)類的定義CRation::CRation(longn,longd){ //對象創(chuàng)建時被調(diào)用
this->n=n; //this是指向當前對象的指針
this->d=d;}voidCRation::Print(void){ cout<<n<<"/"<<d<<endl;}CRation::CRation(longn,longvoidCRation::Gcd() { intx=n,y=d,t; if(x<y) {t=x;x=y;y=t;} t=x%y;while(t!=0){ x=y;y=t;t=x%y; } n/=y;d/=y; }《C類和對象》課件main() {CRationr(18,27);//分配空間,調(diào)構(gòu)造函數(shù)r.Print(); //輸出r.Gcd(); //約分r.Print(); }main() 例:動態(tài)整數(shù)數(shù)組類作為對象的數(shù)組唯一標識的實體封裝數(shù)組元素、元素個數(shù)等信息責任功能按照下標的訪問數(shù)組大小可變可獲取元素個數(shù)#include<iostream.h>#include<string.h>classArray{ int*pElems; intsize; //個數(shù)public: Array(intn); //構(gòu)造 ~Array(void);//析構(gòu)
voidSetAt(inti,intv); intGetAt(inti); //存取
intGetSize(void);}; 例:動態(tài)整數(shù)數(shù)組類作為對象的數(shù)組#include<iost類設計要點獨立性表示獨立的實體以屬性表示其特征以行為表示其擔負的責任(功能、服務)封裝性不開放屬性提供足夠的方法,支持各種用途隱蔽內(nèi)部數(shù)據(jù)結(jié)構(gòu)隱蔽方法的內(nèi)部算法復用性適用性強、功能豐富類設計要點獨立性方法的實現(xiàn)(1/2)Array::Array(intn) { //構(gòu)造n元素的數(shù)組
pElems=newint[n]; //動態(tài)生成
size=n;}Array::~Array(void) { //撤消前被自動調(diào)用
delete[]pElems; //釋放空間}intArray::GetSize(void) { returnsize; //獲得數(shù)組大小}方法的實現(xiàn)(1/2)Array::Array(intn方法的實現(xiàn)(2/2)voidArray::SetAt(inti,intv){ //按下標i賦值v if(i>=size) { //超過范圍
int*p=newint[size+5];//開辟空間,復制數(shù)據(jù)
memcpy(p,pElems,size*sizeof(int)); size+=5; delete[]pElems; //釋放原數(shù)組空間
pElems=p; //保存首地址 } *(pElems+i)=v; //賦值}intArray::GetAt(inti) //按下標i取元素數(shù)據(jù){
returni<size?*(pElems+i):0;} 方法的實現(xiàn)(2/2)voidArray::SetAt(動態(tài)數(shù)組的使用voidmain() { intn; Arrayx(10); //數(shù)組對象實例變量
for(inti=0;i<20;i++) { cout<<"Input:"; cin >>n; x.SetAt(i,n); } for(i=0;i<x.GetSize();i++) cout << x.GetAt(i)<<"";}動態(tài)數(shù)組的使用voidmain() 程序分析對象類=數(shù)據(jù)結(jié)構(gòu)+相關函數(shù)屬性=結(jié)構(gòu)分量方法=作用于結(jié)構(gòu)的函數(shù)對象實例變量靜態(tài)構(gòu)造局部變量、全局變量動態(tài)構(gòu)造new類名(參數(shù)表)函數(shù)定義標識所屬的類可以直接訪問參數(shù)和本類的數(shù)據(jù)成員函數(shù)調(diào)用通過對象實例調(diào)用其方法程序分析對象類=數(shù)據(jù)結(jié)構(gòu)+相關函數(shù)消息傳遞對象方法的激活使用者向?qū)ο髮嵗l(fā)消息對象用方法函數(shù)響應消息消息的組成消息名函數(shù)名消息屬性參數(shù)值的列表核心點使用者僅關心消息的組成對象決定哪個方法負責響應消息傳遞對象方法的激活消息傳遞消息響應不同類可以有同名方法函數(shù)同類中可以有原型不同的方法消息響應方法的選擇消息名=方法名接收消息的對象(對象類)匹配函數(shù)原型(參數(shù)個數(shù)、參數(shù)類型)消息傳遞消息響應對象成員一個類的對象作為另一個類的數(shù)據(jù)成員classX{
類名1成員名1類名2成員名2…...
};構(gòu)造函數(shù)
X::X(參數(shù)表0):成員1(參數(shù)表1),成員2(參數(shù)表2){…...}
對象成員一個類的對象作為另一個類的數(shù)據(jù)成員建立X類對象時,先調(diào)對象成員的構(gòu)造函數(shù),然后才執(zhí)行X類的構(gòu)造函數(shù)對象成員構(gòu)造函數(shù)的調(diào)用順序取決于這些對象成員在類中的說明順序析構(gòu)函數(shù)的調(diào)用順序與構(gòu)造函數(shù)相反建立X類對象時,先調(diào)對象成員的構(gòu)造函數(shù),然后才執(zhí)行X類的構(gòu)造#include"Date.h"classStudent_Info{ intNo; charName[20];charSex;
DateBirthday;
public:Student_Info(intn,char*a,chars,inty,intm,intd);Student_Info();intGetNo();char*GetName();charGetSex();……};#include"Date.h"#include"Student.h"Student_Info::Student_Info(intn,char*a,chars,inty,intm,intd):Birthday(y,m,d){No=n; strcpy(Name,a);Sex=s;}Student_Info::Student_Info():Birthday(2000,1,1){No=0;strcpy(Name,"");Sex='m';}#include"Student.h"程序結(jié)構(gòu)一般分為三個文件:1)將類的說明作為頭文件.h2)將類的成員函數(shù)的實現(xiàn)放一個文件.cpp3)對類的使用放一個文件,包括main.cpp程序結(jié)構(gòu)一般分為三個文件:作業(yè):定義日期類定義描述書的類,包括書名、價格、出版日期等作業(yè):第三章繼承現(xiàn)實世界中的一般特殊關系人學生人教師類的繼承學生類繼承人類教師類繼承人類派生類:描述特殊的屬性和行為基類:描述一般的屬性和行為第三章繼承現(xiàn)實世界中的一般特殊關系C++語言對繼承的支持class派生類:public基類{ … // 特殊屬性 … // 特殊方法 };派生類繼承了基類的屬性和方法支持軟件模塊的復用復用了基類的數(shù)據(jù)結(jié)構(gòu)和成員函數(shù)C++語言對繼承的支持class派生類:publi【例】分別定義一個描述圓的類Circle和描述一個圓柱體的類Cylinder。【例】分別定義一個描述圓的類Circle和描述一個圓柱體的類#ifndefCircle_H#defineCircle_HclassCircle//定義圓類{
protected:doubleradius;public:Circle(doubler){radius=r;}voidsetradius(doubler){radius=r;}doublegetradius(){returnradius;}doublearea(){return3.14*radius*radius;}};#endif#ifndefCircle_H#include"Circle.h"classCylinder:publicCircle//定義圓柱體類{
doubleheight;public:Cylinder(doubler,doubleh);
voidsetheight(doubleh);
doublegetheight();
doublearea();//重新定義area()函數(shù)};#include"Circle.h"#include"Cylinder.h"Cylinder::Cylinder(doubler,doubleh):Circle(r)
{height=h;}voidCylinder::setheight(doubleh){height=h;}doubleCylinder::getheight(){returnheight;}doubleCylinder::area()//重新定義area()函數(shù){return2*Circle::area()+2*3.14*radius*height;}#include"Cylinder.h"#include<iostream.h>#include"Cylinder.h"#include"Circle.h"voidmain(){Circles1(10);Cylinders2(2,5);cout<<"圓柱體表面積:"<<s2.area()<<endl;
cout<<"圓的面積是:"<<s1.area()<<endl;}#include<iostream.h>在創(chuàng)建派生類的對象時,由于派生類的對象包含了基類的數(shù)據(jù)成員,因此派生類的構(gòu)造函數(shù)除初始化其自身定義的數(shù)據(jù)成員外,還必須對基類中的數(shù)據(jù)成員進行初始化,也就是說,派生類的構(gòu)造函數(shù)要負責調(diào)用基類的構(gòu)造函數(shù)。派生類的構(gòu)造函數(shù)的定義格式如下:派生類名::派生類構(gòu)造函數(shù)名(參數(shù)表):基類構(gòu)造函數(shù)名(參數(shù)表){……}在創(chuàng)建派生類的對象時,由于派生類的對象包含了基類的數(shù)據(jù)成員,基類的對象只能調(diào)用基類的成員函數(shù),不能調(diào)用派生類的成員函數(shù)在定義派生類的對象時,系統(tǒng)首先執(zhí)行基類的構(gòu)造函數(shù),然后執(zhí)行派生類的構(gòu)造函數(shù)。而系統(tǒng)執(zhí)行析構(gòu)函數(shù)的順序恰恰相反,即先執(zhí)行派生類的析構(gòu)函數(shù),再執(zhí)行基類的析構(gòu)函數(shù)若在基類中沒有定義任何構(gòu)造函數(shù),這時在派生類的構(gòu)造函數(shù)的定義中可以省略對基類構(gòu)造函數(shù)的調(diào)用,此時系統(tǒng)將去調(diào)用基類的默認構(gòu)造函數(shù)。
基類的對象只能調(diào)用基類的成員函數(shù),不能調(diào)用派生類的成員函數(shù)多繼承定義多繼承類的方式:class派生類名:訪問方式基類1,訪問方式基類2……{……};其中:訪問方式同單繼承多繼承下派生類的構(gòu)造函數(shù)必須同時負責所有基類構(gòu)造函數(shù)的調(diào)用在多繼承下,派生類構(gòu)造函數(shù)的定義格式:派生類構(gòu)造函數(shù)名(參數(shù)表):基類名1(參數(shù)表1),……{……}多繼承定義多繼承類的方式:在多繼承下,系統(tǒng)首先執(zhí)行各基類的構(gòu)造函數(shù),然后再執(zhí)行派生類的構(gòu)造函數(shù),處于同一層次的各基類構(gòu)造函數(shù)的執(zhí)行順序與聲明派生類時所指定的各基類順序一致,而與派生類的構(gòu)造函數(shù)定義中所調(diào)用基類構(gòu)造函數(shù)的順序無關。在多繼承下,系統(tǒng)首先執(zhí)行各基類的構(gòu)造函數(shù),然后再執(zhí)行派生類的第四章多態(tài)性與虛函數(shù)多態(tài)性不同事物以不同方式響應同一消息演出發(fā)消息“暫?!苯o 比賽會議產(chǎn)生不同的消息響應消息響應取決于接受消息的對象,而不是發(fā)送者第四章多態(tài)性與虛函數(shù)多態(tài)性【例】#include<iostream.h>classA{inta;public:A(inti=0){a=i;}voidprint();};voidA::print(){cout<<"InclassA,print()iscalled."<<endl;}【例】classB:publicA
{intb;public:B(intj=-1){b=j;}
voidprint();};voidB::print(){cout<<"InclassB,print()iscalled."<<endl;}classB:publicAvoidmain(){Aa,*pa;Bb,*pb;pa=&a;pa->print();pb=&b;pb->print();
pa=&b;//基類指針可以指向派生類對象
pa->print();}voidmain()《C類和對象》課件voidcommfun(A&aref){aref.print();}voidmain(){Aa;a.print();commfun(a);//以基類A的對象a作實參Bb;b.print();commfun(b);//以派生類B的對象b作實參}voidcommfun(A&aref)《C類和對象》課件分析:在派生類B中繼承了基類A的成員函數(shù)print(),又定義了一個同名的print()函數(shù)。這種改變在靜態(tài)聯(lián)編的基礎上編譯器并不知道。必須通知編譯器這種可能的改變,即需要進行動態(tài)聯(lián)編。其方法就是在基類中將可能發(fā)生改變的成員函數(shù)聲明為虛函數(shù)。分析:在派生類B中繼承了基類A的成員函數(shù)print(),又定虛函數(shù)聲明虛函數(shù)的方法是在基類中的成員函數(shù)原型前加上關鍵字virtual。其格式如下:
class類名{……
virtual
類型函數(shù)名(參數(shù)表);……};虛函數(shù)聲明虛函數(shù)的方法是在基類中的成員函數(shù)原型前加上關鍵字v當一個類的成員函數(shù)說明為虛函數(shù)后,在該類的派生類中定義與其基類虛函數(shù)原型相同的函數(shù)。這時,當用基類指針指向這些派生類對象時,系統(tǒng)會在程序運行中根據(jù)所指對象的不同,自動選擇派生類中的同名函數(shù)來代替基類中的虛函數(shù)。當一個類的成員函數(shù)說明為虛函數(shù)后,在該類的派生類中定義與其基虛函數(shù)在派生類中重新定義時,必須與基類中的函數(shù)原型完全相同,包括函數(shù)名、返回類型、參數(shù)個數(shù)和參數(shù)類型的順序。這時無論在派生類的相應成員函數(shù)前是否加上關鍵字virtual,都將視其為虛函數(shù)。如果函數(shù)原型不同,只是函數(shù)名相同,C++將視其為一般的函數(shù)重載,而不是虛函數(shù)。虛函數(shù)在派生類中重新定義時,必須與基類中的函數(shù)原型完全相同,#include<iostream.h>classP{public:
virtualvoidprint(){cout<<"ParentClass"<<endl;}};classA:publicP{public:
virtualvoidprint(){cout<<"SubClass1"<<endl;}};classB:publicP{public:
virtualvoidprint(){cout<<"SubClass2"<<endl;}};#include<iostream.h>voidmain(){Aobj1;Bobj2;P*s1; s1=&obj1;s1->print();s1=&obj2;s1->print();}通過指針voidmain()通過指針classA{public:
virtualvoidPrint(){cout<<"Parent"<<endl;}};classB:publicA{public: virtualvoidPrint(){cout<<"Subclass"<<endl;}};voidshow(A&a){ a.Print();}通過引用classA{通過引用voidmain(){Bb;show(b);}voidmain()純虛函數(shù)在基類中只聲明虛函數(shù)而不給出具體的函數(shù)定義體,將它的具體定義放在各派生類中,稱此虛函數(shù)為純虛函數(shù)。通過該基類的指針或引用就可以調(diào)用所有派生類的虛函數(shù),基類只是用于繼承,僅作為一個接口,具體功能在派生類中實現(xiàn)。形式:virtual類型函數(shù)名(參數(shù)表)=0;純虛函數(shù)在基類中只聲明虛函數(shù)而不給出具體的函數(shù)定義體,將它的抽象類若一個類至少有一個純虛函數(shù),就稱該類為抽象類。抽象類中可以有多個純虛函數(shù),也可以定義其他非純虛函數(shù)。抽象類若一個類至少有一個純虛函數(shù),就稱該類為抽象類。不能聲明抽象類的對象,但可以聲明指向抽象類的指針變量和引用變量。如果派生類中沒有重新定義基類中的純虛函數(shù),則在派生類中必須再將該虛函數(shù)聲明為純虛函數(shù)。從抽象類可以派生出具體或抽象類。引入抽象類的目的,主要是為了能將相關類組織在一個類繼承結(jié)構(gòu)中,并通過抽象類來為這些相關類提供統(tǒng)一的操作接口。不能聲明抽象類的對象,但可以聲明指向抽象類的指針變量和引用變【例】設計一個抽象類shape,它表示具有形狀的東西,體現(xiàn)了抽象的概念,在它下面可以派生出多種具體形狀,比如三角形、矩形。#include<iostream.h>classShape{protected:doublex,y;public:voidset(doublei,doublej){x=i;y=j;}virtualvoidarea()=0;//聲明純虛函數(shù)};【例】設計一個抽象類shape,它表示具有形狀的東西,體現(xiàn)classTriangle:publicShape{public:voidarea(){cout<<"三角形面積:"<<0.5*x*y<<endl;}};classRectangle:publicShape{public:voidarea(){cout<<"矩形面積:"<<x*y<<endl;}};classTriangle:publicShapevoidshowarea(Shape&s){ s.area()
溫馨提示
- 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 個人保險理賠授權委托書
- 單次包車合同范本
- 口罩委托采購合同范本
- 獸藥代理合同范本
- 世界水日活動策劃方案
- 下學期幼兒教師的個人總結(jié)
- 推拿治療學模擬題+答案
- 別墅建設合同范本
- 勞務合同補充合同范本
- 發(fā)光字安裝合同范本
- 安全生產(chǎn)個臺賬內(nèi)容
- 建設工程項目-月度安全檢查表
- 硬件設計的模塊化
- 學校食堂食品安全投訴舉報登記表
- 梁湘潤.命學精華
- 六年級上冊心理健康課件6《健康上網(wǎng)快樂多》(27張PPT)
- 城市軌道交通工程施工組織設計與概預算PPT全套完整教學課件
- 全國青少年機器人技術等級(機器人二級)考試復習題庫(含真題)
- 學習弘揚雷鋒精神課件
- 行政區(qū)域代碼表Excel
- 精神病醫(yī)院管理制度
評論
0/150
提交評論