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

下載本文檔

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

文檔簡(jiǎn)介

1、第3章 類和對(duì)象 本章介紹類與對(duì)象的定義、成員函數(shù)、構(gòu)造函數(shù)、析構(gòu)函數(shù)、對(duì)象與指針等基本概念及應(yīng)用,講解C+的繼承、重載、多太性等特性,使讀者掌握C+的編程基本知識(shí)。3.1 類與對(duì)象的定義3.2 成員函數(shù)3.3 構(gòu)造函數(shù)3.4 析構(gòu)函數(shù)3.5 對(duì)象與指針3.6 類與結(jié)構(gòu)3.7 繼承3.8 多重繼承3.9 派生類的對(duì)象和構(gòu)造函數(shù)3.10 多態(tài)性3.11 重載3.12 虛擬函數(shù)實(shí)驗(yàn)3 類和對(duì)象、繼承和派生 1類的定義類定義的語法如下: class類名 private: 數(shù)據(jù)成員或成員函數(shù); public: 數(shù)據(jù)成員或成員函數(shù); protected: 數(shù)據(jù)成員或成員函數(shù); ; 3.1 類與對(duì)象的定義

2、 類的定義由兩大部分組成,即類的數(shù)據(jù)成員和成員函數(shù)。類的數(shù)據(jù)成員和成員函數(shù)也稱為類的屬性和類的操作。數(shù)據(jù)成員類似C結(jié)構(gòu)中的變量,成員函數(shù)定義了類對(duì)數(shù)據(jù)的操作,反映了類行為和類的能力。 例3.1:定義一個(gè)student類,用以描述學(xué)生對(duì)象。 123 class Student private: char m_Name20; int m_Age; int m_Sex; char m_cl20; int m_number;public:void Register(char * Name,int Age,char Sex,char * cl,int number); void GetName(char

3、 * Name); int GetAge(); char GetSex(); void Getcl(char * cl); int Getnumber();程序?qū)崿F(xiàn):2對(duì)象的定義 對(duì)象是類的實(shí)例。從技術(shù)上講,一個(gè)對(duì)象就是一個(gè)具有某種類類型的變量。與普通變量一樣,對(duì)象也必須先經(jīng)聲明才可以使用。 聲明一個(gè)對(duì)象的一般形式為:,,例:Student Student1, Student2;聲明了兩個(gè)名為Student1和Student2的Student類的對(duì)象。 在程序中使用一個(gè)對(duì)象,通常是通過對(duì)體現(xiàn)對(duì)象特征的數(shù)據(jù)成員的操作實(shí)現(xiàn)的。當(dāng)然,由于封裝性的要求,這些操作又是通過對(duì)象的成員函數(shù)實(shí)現(xiàn)的。具體來說:

4、(1)成員函數(shù)訪問同類中的數(shù)據(jù)成員,或調(diào)用同類中的其他成員函數(shù),可直接使用數(shù)據(jù)成員名或成員函數(shù)名;(2)在對(duì)象外訪問其數(shù)據(jù)成員或成員函數(shù)需使用運(yùn)算符“.”訪問對(duì)象的成員,例如:number= Student1.Getnumber();(3)不能直接訪問一個(gè)對(duì)象中的私有成員,如果直接訪問則導(dǎo)致語法錯(cuò)誤;(4)同類對(duì)象之間可以整體賦值。例如:Student2=Student1;(5)對(duì)象用作函數(shù)的參數(shù)時(shí)屬于賦值調(diào)用;函數(shù)可以返回一個(gè)對(duì)象。3.2 成員函數(shù) 在類的定義中僅給出了成員函數(shù)的原型,函數(shù)的定義還需在其他地方(通常每個(gè)類的成員函數(shù)的定義放在一起構(gòu)成一個(gè)源程序文件)給出。 類的成員函數(shù)的一般形

5、式為: :函數(shù)名() 函數(shù)體 其中作用域運(yùn)算符“:”指出成員函數(shù)的類屬。沒有類屬的函數(shù)稱為公共函數(shù)。 例3.2.1 類成員函數(shù)的定義。 說明:按例3-1說明的方法添加頭文件Student.h,輸入Student類的定義。然后為項(xiàng)目添加一源代碼文件Student.cpp /Example(Student.cpp): Student類成員函數(shù)的定義#include#include“Student.h”void Student:Register(char * Name,int Age,char Sex,char * class,int number); strcpy (m_Name, name);

6、m_Age =age;m_Sex=(sex =m? 0:1);strcpy (m_ cl, cl);m_ number= number; void Student :GetName (char *name) strcpy (name,m_Name); int Student:GetAge() return m_Age; char Student:GetSex() return (m_Sex=0? m: f): void Student:Getcl(char * cl)strcpy (cl,m_ cl);int Student:Getnumber()return m_number例3.2.2 定

7、義Student類,并將類Student的成員函數(shù)聲明為內(nèi)聯(lián)函數(shù) 。 cl Student private: char m_Name20; int m_Age; int m_Sex; char m_cl20; int m_number;public: void Register(char * Name,int Age,char Sex,char * cl,int number) strcpy (m_Name, name); m_Age =age;m_Sex=(sex =m? 0:1);strcpy (m_ cl, cl);m_ number= number;void GetName(char

8、* Name) strcpy (name,m_Name); int GetAge() return m_Age; char GetSex() return (m_Sex=0? m: f); void Getcl(char * cl)strcpy (cl,m_ cl);int Getnumber()return m_number;例3.2.3學(xué)生資料的輸入輸出。 /Example: 學(xué)生資料的輸入和輸出#include#void main()void OutStudentData(Student);char name20,sex;int age;char cl20;int number;Stud

9、ent Student1,Studen2;coutnameage sexclnumber;Student1.Register(name, age, sex, cl, number);Student2.Register(“Zhang2”,19,m,“9901”,100);cout“student 1:t”;OutStudentData(Student1);cout“Student2:t”;OutStudentData(Student2);Student2=Student1;Cout“Student3:t”;OutStudentData(Student2);void OutStudentData(

10、Student);char name20;char cl20;Student.GetName(name);Student.GetCl(cl)coutname“t”Student.GetAge()“t”Student.GetSex()“t”cl “t”Student.Getnumber()end1; Enter a Students name、age、sex、cl and number:zhang1 20 f “9901” 101輸入:Student1: zhang1 20 f 9901 101輸出Enter a Students name、age、sex、cl and number:zhang

11、2 19 m “9902” 100輸入:Student2: zhang2 19 m 9902 100輸出Enter a Students name、age、sex、cl and number:zhang3 20 f “9901” 102輸入:Student3: zhang3 20 f 9901 102輸出3.3 構(gòu)造函數(shù) 構(gòu)造函數(shù)是與類名相同的特殊成員函數(shù),當(dāng)定義對(duì)象或者用new 動(dòng)態(tài)生成對(duì)象時(shí),編譯程序?qū)⒆詣?dòng)調(diào)用構(gòu)造函數(shù)以實(shí)現(xiàn)對(duì)象的初始化。構(gòu)造函數(shù)與普通成員函數(shù)的區(qū)別,是不允許指定返回類型,也不返回值。構(gòu)造函數(shù)允許重載。 構(gòu)造函數(shù)的聲明格式為: (); 例3.3.1 為類Student增加構(gòu)

12、造函數(shù)。 /Example:為類Student增加構(gòu)造函數(shù)#includeclass StudentPrivate: char m_Name20; int m_Age; int m_Sex; char m_cl20; int m_number;Public: Student (const char *name,int age ,char sex,const char cl,int number) /構(gòu)造函數(shù)strcpy(m_Name,name);m_Age=age;m_Sex=(sex=m?0:1);strcpy(m_cl,cl);m_number=number; void Register(

13、char * Name,int Age,char Sex,char * cl,int number); void GetName(char * Name); int GetAge(); char GetSex(); void Getcl(char * cl); int Getnumber();說明:如果在類中沒有聲明任何構(gòu)造函數(shù)的話,系統(tǒng)會(huì)自動(dòng)地為它定義一個(gè)形如 :()的缺省構(gòu)造函數(shù),這種不帶任何參數(shù)且函數(shù)體為空的構(gòu)造函數(shù)就叫做缺省的構(gòu)造函數(shù)。如果在類聲明中已經(jīng)定義了構(gòu)造函數(shù),則系統(tǒng)不再提供缺省的構(gòu)造函數(shù)。 3.4 析構(gòu)函數(shù) 析構(gòu)函數(shù)的函數(shù)名是在類名前加波浪名“”的特殊成員函數(shù)。析構(gòu)函數(shù)與構(gòu)造

14、函數(shù)的功能正好相反;構(gòu)造函數(shù)在對(duì)象生成時(shí)為其他分配存儲(chǔ)空間,而析構(gòu)函數(shù)的功能是在對(duì)象銷毀時(shí)釋放它所占用的內(nèi)存。析構(gòu)函數(shù)與構(gòu)造函數(shù)一樣沒有返回值,但它不帶參數(shù),不能被重載。 析構(gòu)函數(shù)的聲明方法為: class Example public: Example(); /析構(gòu)函數(shù); ; 當(dāng)類的聲明中沒有定義析構(gòu)函數(shù)時(shí),編譯程序會(huì)自動(dòng)產(chǎn)生一個(gè)默認(rèn)的析構(gòu)函數(shù)。 例: include class Example public: Example(); Example(); Example()cout“Object is created!”n;Example: Example()cout“Object is d

15、estroyed!”,例如: Ptr-GetAge(); 當(dāng)對(duì)象接收到一個(gè)消息時(shí),便會(huì)調(diào)用相應(yīng)的成員函數(shù)。這時(shí),系統(tǒng)會(huì)向該成員函數(shù)傳遞一個(gè)隱含的參數(shù),即指向該對(duì)象自身的指針,即this指針。一般來說,this指針用途不大,因?yàn)樵诔蓡T函數(shù)中可以直接使用本對(duì)象內(nèi)部的所有成員變量和成員函數(shù)。但在某些場(chǎng)合中調(diào)用其他類的成員函數(shù)時(shí),可能需用要傳送本對(duì)象的地址,在Windows程序設(shè)計(jì)中這種情況很多,這時(shí)就要用到this指針。 3.6 類與結(jié)構(gòu) C+中有一個(gè)結(jié)構(gòu)體類型,其定義和使用方法與類非常相似。 結(jié)構(gòu)體類型的定義方法如下: Struct ;例:可定義一個(gè)表示日期的結(jié)構(gòu)體類型。 struct datei

16、nt da_year;int da_mon;int da_day; 即一個(gè)日期類型的變量有3個(gè)成員變量: 年份(da_year)、月份(da_mon)和日(da_day)。 在定義好結(jié)構(gòu)體類型以后,就可以定義該類型的變量了: struct ;注意在定義時(shí)可以略去結(jié)構(gòu)體類型說明符struct,這一點(diǎn)與C語言不同。例:變量聲明語句。 date yesterday, today,tomorrow;聲明了3個(gè)日期類型的變量:yesterday、today和tomorrow。 結(jié)構(gòu)體類型的變量可用作函數(shù)的參數(shù)或者函數(shù)的返回值。 對(duì)結(jié)構(gòu)體類型變量的成員變量的引用方法與類相同: .例: today.da_y

17、ear=2001; today.da_mon=10; today.da_day=10;3.7 繼承 繼承性是面向?qū)ο蟪绦蛟O(shè)計(jì)語言的主要特征之一。 繼承性指的是一個(gè)新類可以從現(xiàn)有的類中派生出來,繼承該類的特性。被繼承的類稱為基類(base class)或父類(parent class),繼承的類稱為派生類(derived class)或子類(child class)。 繼承性允許建立類層次結(jié)構(gòu),是程序中代碼可復(fù)用性的關(guān)鍵,并提供對(duì)多態(tài)性的支持,是C+面向?qū)ο蟪绦蛟O(shè)計(jì)的基石。3.7 繼承 1繼承與類層次結(jié)構(gòu)生物動(dòng)物植物微生物爬行動(dòng)物哺乳動(dòng)物鳥類貓科動(dòng)物貓圖 人類認(rèn)識(shí)事物的抽象層次 在軟件設(shè)計(jì)中,人

18、們模擬這一過程。在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,繼承提供了重用已有代碼生成新類的方法。繼承在類之間建立了關(guān)系。子類可以繼承父類的所有數(shù)據(jù)結(jié)構(gòu)和操作,只要在子類中添加父類沒有的數(shù)據(jù)結(jié)構(gòu)和操作。 在上圖中,對(duì)象類型CButton是從CWnd派生出來的,CWnd是從CCmdTarget派生出來的,而CCmdTarget又是從CObject派生出來的。CObjectCCmdTargetCByteArrayCCmdTargetCframeWndCDialogCButton2派生類的工作方式 在C+程序中,當(dāng)一個(gè)類是從一個(gè)基類派生出來的時(shí)候,該派生類就繼承了基類所有的成員變量和成員函數(shù),而且可以加入自己的成員變量

19、和成員函數(shù)。但是,基類中聲明為私有的成員變量和成員函數(shù)是不可為派生類訪問的。 基 類變量1變量2函數(shù)1函數(shù)2派生類其他變量其他函數(shù)圖 說明基類和派生類之間的層次關(guān)系 3派生一個(gè)類 聲明一個(gè)派生類的語法形式為: class 派生類名稱:繼承權(quán)限 基類名稱 ; 其中,繼承權(quán)限說明符有三種:public、private和protected,默認(rèn)權(quán)限為private。在類的定義中,所有公有成員都允許其他函數(shù)訪問,而私有成員則只能供成員函數(shù)訪問。但是,當(dāng)派生類繼承基類的特性時(shí),派生類無法訪問基類中的私有成員。若想讓基類中的某些成員不僅可供成員函數(shù)訪問,而且可將其特性傳給派生類,那么應(yīng)將其聲明為保護(hù)類型。

20、 例:類繼承的例子 。 #include class parent /聲明基類int i; /私有成員變量i僅供成員函數(shù)使用,不能傳遞給派生類protected: /受保護(hù)成員變量?jī)H供成員函數(shù)使用,可供派生類使用int x;public: /公有成員,可供任何函數(shù)使用parent();void change();void show();parent:parent() /定義構(gòu)造函數(shù)x=0;i=0;void parent:change() /定義成員函數(shù)x+;i+;void parent:show()/定義成員函數(shù)cout”x=”x”n”;class son:public parent/聲明so

21、n為parent的派生類,繼承權(quán)限為public,即parent類的/公有成員在son中仍為公有成員,parent類的保護(hù)成員在son中仍為/保護(hù)成員public:void increase(); /聲明成員函數(shù);void son:increase() /定義成員函數(shù)體x+;保護(hù)成員變量x公有成員函數(shù)parent公有成員函數(shù)change公有成員函數(shù)increase公有成員函數(shù)show 經(jīng)過類繼承,派生類son訪問以下成員 例 某公司使用EMPINFO程序管理自己的雇員信息。后來,當(dāng)該公司在國(guó)外開了分支機(jī)構(gòu)而且雇傭不止一個(gè)國(guó)家的雇員時(shí),如何重新設(shè)計(jì)EMPINFO程序呢? 提示:為了滿足跨國(guó)公司的

22、需要,程序設(shè)計(jì)者從EMPINFO程序中使用的EmpInfo類派生了一個(gè)新類,名為OffshoreEmpInfo。 #include class EmpInfo /基類public:EmpInfo() /構(gòu)造函數(shù)和析構(gòu)函數(shù)EmpInfo() private:char * m_name;char * m_dept;char * m_position;long m_salary;public:void SetName(char * name) m_name = name; /設(shè)置員變量的值void SetDept(char * dept) m_dept = dept;void SetPosition

23、(char * position)m_position = position;SetSalary(long salary)m_salary = salary;void PrintInfo();class OffshoreEmpInfo:public EmpInfo /派生類public:OffshoreEmpInfo() /構(gòu)造函數(shù)和析構(gòu)函數(shù)OffshoreEmpInfo() private:char * m_country;public:void SetCountry(char * country)m_country = country;void PintInfo();void EmpInf

24、o:PrintInfo()cout ”Name:” m_name ”n”; cout ”Department:” m_dept ”n”;cout ”Position:” m_position ”n”;cout ”Salary:” m_salary ”n”;void OffshoreEmpInfo:PrintInfo()EmpInfo:PrintInfo();Cout “Country:” m_Country “n”;int main() OffshoreEmpInfo empInfo; /定義類OffshoreEmpInfo的對(duì)象empInfo.SetName(“Paul Norton”);e

25、mpInfo.SetDept(“Development”);empInfo.SetPosition(“Engineer”);empInfo.SetSalary(24000);empInfo.SetCountry(“New Zealand”);empInfo.PrintInfo();return 0;Name: Paul NortonDepartment: DevelopmentPosition: EngineerSalary:24000Country: New Zealand輸出 3.8 多重繼承 基類與派生類之間可以有復(fù)雜的多對(duì)多關(guān)系。在類繼承中,允許某個(gè)類同時(shí)繼承多個(gè)基類,即所謂類的多重繼

26、承。在類的多重繼承中,基類和派生類間是多對(duì)一的關(guān)系?;?基類2基類n派生類繼承 繼承 繼承 繼承 通過多重繼承,派生類將繼承多個(gè)基類的特性,此時(shí)基類和派生類的聲明方式為: class N1 /聲明基類N1 ; class Nm/聲明基類Nm ; class S: public N1, ,public Nm /聲明派生類S同時(shí)繼承基類N1, ,基類Nm ;注意:繼承一個(gè)以上的基類,要使用逗號(hào)分隔的表,還要確保為每個(gè)被繼承的基類使用一個(gè)繼承權(quán)限說明符。 例:兩用沙發(fā)是一個(gè)沙發(fā),也是一張床,兩用沙發(fā)同時(shí)具有沙發(fā)和床的特性。程序中類SleeperSofa繼承Bed和Sofa兩個(gè)類。#include

27、class Sofaprotected:int length;public:Sofa():length(0)void SitOn() coutSitting.n;void SetLength(int i) length=i;class Bedprotected:int length;public:Bed():length(0)void Sleep() coutSleeping.n;void SetLength(int i) length=i;class SleepSofa: public Sofa,public Bed/繼承多個(gè)基類public:SleepSofa()void FoldOut(

28、) /折疊與打開cout”Folt/Out the sofa.n”;void main()SleepSofa sf;sf.SitOn();sf.FoldOut();sf.Sleep();Sitting.Folt/Out the sofa.Sleeping. 運(yùn)行結(jié)果 3.9 派生類的對(duì)象和構(gòu)造函數(shù)1派生類的對(duì)象 用某個(gè)基類聲明一個(gè)派生類后,仍然可以利用基類來聲明對(duì)象,而且所聲明的對(duì)象和派生類所聲明的對(duì)象不會(huì)沖突。 void main() son ob1;/用派生類son定義一個(gè)對(duì)象ob1 parent ob2;/用基類parent定義一個(gè)對(duì)象ob2 cout”Display derived c

29、lass object ob1 ”; ob1.show();/對(duì)象ob1的顯示結(jié)果 ob1.change();/調(diào)用從基類中繼承的成員函數(shù) ob1.increase();/調(diào)用派生類中聲明的成員函數(shù) cout”Display base class object ob2 ”; ob2.change(); ob2.show();Display derived class object ob1 x=0Display base class object ob2 x=1運(yùn)行結(jié)果1派生類的對(duì)象 用某個(gè)基類聲明一個(gè)派生類后,仍然可以利用基類來聲明對(duì)象,而且所聲明的對(duì)象和派生類所聲明的對(duì)象不會(huì)沖突。 void

30、 main() son ob1;/用派生類son定義一個(gè)對(duì)象ob1 parent ob2;/用基類parent定義一個(gè)對(duì)象ob2 cout”Display derived class object ob1 ”; ob1.show();/對(duì)象ob1的顯示結(jié)果 ob1.change();/調(diào)用從基類中繼承的成員函數(shù) ob1.increase();/調(diào)用派生類中聲明的成員函數(shù) cout”Display base class object ob2 ”; ob2.change(); ob2.show();Display derived class object ob1 x=0Display base c

31、lass object ob2 x=1運(yùn)行結(jié)果2派生類對(duì)象的構(gòu)造函數(shù)和析構(gòu)函數(shù)#include class basepublic:base() cout”Constructing basen”; base() cout”Destructing basen”;class derived : public basepublic:derived() cout” cout”Constructing derivedn”; base() cout”Destructing derivedn”;main()derived ob; /do nothing but construct and destruct o

32、breturn 0;Constructing baseconstructing derivedDestructing derivedDestructing base運(yùn)行結(jié)果 由此可得出一般性的結(jié)論:當(dāng)創(chuàng)建派生類的對(duì)象時(shí),如果基類包含構(gòu)造函數(shù),它將首先執(zhí)行,派生類的構(gòu)造函數(shù)緊隨其后。當(dāng)撤消派生類的對(duì)象時(shí),它的析構(gòu)函數(shù)將首先執(zhí)行,如果基類包含析構(gòu)函數(shù),其析構(gòu)函數(shù)將緊隨其后。換句話說,構(gòu)造函數(shù)按其引入的順序執(zhí)行,析構(gòu)函數(shù)按其引入的相反順序執(zhí)行。 在多層繼承的情況下(即一個(gè)派生類成為另一個(gè)派生類的基類),一般規(guī)則是,構(gòu)造函數(shù)按引入的順序執(zhí)行,析構(gòu)函數(shù)按反序執(zhí)行。 3向基類構(gòu)造函數(shù)傳遞參數(shù) 如何向基類的

33、構(gòu)造函數(shù)傳遞參數(shù)呢?答案是使用向一個(gè)或多個(gè)基類的構(gòu)造函數(shù)傳遞參數(shù)的派生類構(gòu)造函數(shù)聲明的擴(kuò)展格式即可。 這種擴(kuò)展的派生類構(gòu)造函數(shù)聲明的一般格式為: derived_constructor(arg_list): base1(arg_list), base2(arg_list), baseN(arg_list); /body of derived constructor 其中,base1到baseN是派生類繼承的基類名。注意,在有多個(gè)基類的情況下,用冒號(hào)將派生類的構(gòu)造函數(shù)說明和基類分開,用逗號(hào)將基類分開。例 3.9.2 下面的例子使用了多個(gè)基類。 #include class base1protec

34、ted: int i;public: base1(int x) i=x; cout”Constructing base1n”; /基類1的有參構(gòu)造函數(shù) base1() cout”Destructing base1n”;class base2protected: int k;public: base2(int x) k=x; cout”Constructing base2n”; /基類2的有參構(gòu)造函數(shù) base2() cout”Destructing base2n”;class derived:public base1,public base2 int j;public: derived(int

35、 x, int y, int z): base1(y),base2(z) / derived使用x, y,z傳遞參數(shù)給基類構(gòu)造函數(shù)j=x; cout” Constructing derivedn”; derived() cout” Destructing derivedn”; void show() couti” ”j” ”k”n”;main() derived ob(3,4,5); /定義類derived的對(duì)象ob ob.show();/顯示 4 3 5return 0;Constructing base1Constructing base2Constructing derived4 3 5

36、Destructing derivedDestructing base2Destructing base1運(yùn)行結(jié)果1多態(tài)性(polymorphism) 多態(tài)性指的是一個(gè)接口名稱具有多種功能,是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特性之一。C+有兩種多態(tài)性,一是靜態(tài)的多態(tài)性,一是運(yùn)行時(shí)的多態(tài)性。所謂靜態(tài)的多態(tài)性,是指操作作用的確切對(duì)象是在運(yùn)行之前(即編譯時(shí))就能確定的,所以相應(yīng)的反應(yīng)也是在運(yùn)行之前就能確定的,這種多態(tài)性在C+中是用重載實(shí)現(xiàn)的。所謂運(yùn)行時(shí)的多態(tài)性,是指操作作用的確切對(duì)象依賴于運(yùn)行的進(jìn)程,其相應(yīng)的反應(yīng)必須在運(yùn)行時(shí)動(dòng)態(tài)給出。C+是通過虛擬函數(shù)(virtual function)實(shí)現(xiàn)這種多態(tài)性的。 2

37、靜態(tài)聯(lián)編與動(dòng)態(tài)聯(lián)編 聯(lián)編是指將函數(shù)調(diào)用與相應(yīng)的函數(shù)體代碼彼此關(guān)聯(lián)的過程,若此過程在程序開始運(yùn)行前的編譯階段完成,稱為靜態(tài)聯(lián)編。 與靜態(tài)聯(lián)編不同,在程序運(yùn)行時(shí)進(jìn)行的聯(lián)編方式,稱為動(dòng)態(tài)聯(lián)編。一般說來,動(dòng)態(tài)聯(lián)編是通過指針來實(shí)現(xiàn)的。 3.10 多態(tài)性 3.11 重載1函數(shù)重載(1)函數(shù)重載及其好處 函數(shù)重載允許一個(gè)程序內(nèi)聲明多個(gè)名稱相同的函數(shù),這些函數(shù)可以完成不同的功能,并可以帶有不同類型、不同數(shù)目的參數(shù)及返回值。使用函數(shù)重載可以減輕用戶的記憶負(fù)擔(dān),并使程序結(jié)構(gòu)簡(jiǎn)單、易懂。 重載包含函數(shù)重載和操作符重載,是C+語言提供的一個(gè)重要特性。重載不僅為編譯時(shí)的多態(tài)性提供了大部分支持,而且使得語言具有很大的靈活

38、性和易擴(kuò)展性。 #include int Abs(int i);double Abs(double d);long Abs(long l); /程序包含三個(gè)名為Abs的重載版本的函數(shù)main() cout Abs(-10) ”n”; cout Abs(-12.0) ”n”; cout Abs(-7L) ”n”; return 0;int Abs(int i) cout “using integer Abs()n”; return i0?-i:i;double Abs(double d) cout “using double Abs()n”; return d0.0?-d:d;long Abs(

39、long l) cout “using long Abs()n”; return l0?-l:l;(2)函數(shù)重載的基本規(guī)則 重載函數(shù)時(shí)我們必須遵守一個(gè)基本規(guī)則:你提供給編譯程序的重載函數(shù)必須在它們的參數(shù)類型或參數(shù)數(shù)量上不同。 #include int myfunc(int i);int myfunc(int i, int j);/重載函數(shù)具有不同數(shù)目的參數(shù)main() cout myfunc(20) ”n”;/ 調(diào)用myfunc(int i) cout myfunc(3,4) ”n”;/ 調(diào)用myfunc(int i,int j) return 0;int myfunc(int i) retu

40、rn i;int myfunc(int i, int j) return i*j;(3)重載成員函數(shù) 在類的成員函數(shù)和構(gòu)造函數(shù)上,也可以直接使用函數(shù)重載的概念。例如,假設(shè)你要寫兩個(gè)不同的函數(shù)來顯示一個(gè)窗口,一個(gè)函數(shù)要求提供大小作為一個(gè)參數(shù),另一個(gè)不要求參數(shù)但使用缺省尺寸??梢砸赃@種形式寫一對(duì)重載的成員函數(shù): void DisplayWindow(); void DisplayWindow(CRect winRect); 創(chuàng)建完這些重載的成員函數(shù)之后,就可以調(diào)用任意一個(gè)。這個(gè)語句將調(diào)用第一個(gè)DisplayWindow函數(shù): DisplayWindow();下面的語句將調(diào)用第二個(gè)DisplayWi

41、ndow函數(shù): CRECT winRect(10,10,50,200); DisplayWindow(winRect);(4)重載構(gòu)造函數(shù)在C+中,構(gòu)造函數(shù)經(jīng)常被重載。許多構(gòu)造函數(shù)有兩個(gè)甚至更多的版本。class Exampleint x;public:Example() x=0;/定義重載的構(gòu)造函數(shù)Example(int a) x=a;void display();定義重載的構(gòu)造函數(shù)后,聲明對(duì)象時(shí)就可以根據(jù)不同的參數(shù)來分別調(diào)用不同的構(gòu)造函數(shù)。例如:void main()Example A;/自動(dòng)調(diào)用構(gòu)造函數(shù)Example()Example B(3);/自動(dòng)調(diào)用構(gòu)造函數(shù)Example(int

42、a)#include #include class dateint day, month, year;public:date(char *d);date(int m, int d, int y);void show_date();date:date(char *d) /用字符串初始化sscanf(d,”%d%*c%d%*c%d”,&month,&day,&year);date:date(int m, int d, int y)/用整數(shù)初始化day=d;month=m;year=y;void date:show_date()cout month ”/” day;cout ”/” year ”n”

43、;main()date ob1(3,6,2000), ob2(”10/21/1999”);ob1.show_date();ob2.show_date();return 0;mm/dd/yyyymain()char s80;cout s;date d(s);d.show_date();return 0;(5)派生類中的重載函數(shù)#include class Aclassprivate:int aVal;public:Aclass() Aclass() int Value(int n) aVal = n+1; return aVal;class Bclassprivate:float bVal;pu

44、blic:int Value(float n) bVal = n+2; return bVal;int main()Bclass anob;cout anob.Value(100) n;return 0;(6)作用域操作符int main()Bclass anobject;cout anobject.Aclass:Value(100) n;/使用作用域操作符來調(diào)用Aclass:Value()return 0;2操作符重載(1)編寫操作符重載函數(shù)函數(shù)類型 operator#(形參表)/函數(shù)體(2)操作符重載函數(shù)的作用域Money operator+(int)/函數(shù)體(3)C+如何實(shí)現(xiàn)操作符重載(

45、5)操作符重載舉例AClass.operator+();AClass AClass:operator+() /body of function+aObject;#include #include #include #include class Money private:double dollars;double cents;public:Money() /定義構(gòu)造函數(shù)Money() /定義析構(gòu)函數(shù)Money(double d, double c);/另一構(gòu)造函數(shù)Money(double);/從double轉(zhuǎn)換Money operator+(); /操作符重載double GetAmount(

46、double &n);Money Money:operator+()cents+;if(cents 99) dollars+;cents = 0;return *this;Money:Money(double d, double c)dollars = d; cents = c;Money:Money(double cash)/一個(gè)轉(zhuǎn)換構(gòu)造函數(shù)/將浮點(diǎn)值轉(zhuǎn)換成Money值double frac,n;frac = modf(cash,&n);/一個(gè)math.h函數(shù)cents = frac * 100;dollars = n;double Money:GetAmount(double &n)n=d

47、ollars;return cents;int main()double c,d;Money myCash(7.99);c = myCash.GetAmount(d);cout d dollarsn;cout c centsn;+myCash;c = myCash.GetAmount(d);cout d dollarsn;cout c 99)dollars+;cents=0;return *this;(4)重載構(gòu)造函數(shù)在C+中,構(gòu)造函數(shù)經(jīng)常被重載。許多構(gòu)造函數(shù)有兩個(gè)甚至更多的版本。class Exampleint x;public:Example() x=0;/定義重載的構(gòu)造函數(shù)Example

48、(int a) x=a;void display(); 定義重載的構(gòu)造函數(shù)后,聲明對(duì)象時(shí)就可以根據(jù)不同的參數(shù)來分別調(diào)用不同的構(gòu)造函數(shù)。void main()Example A;/自動(dòng)調(diào)用構(gòu)造函數(shù)Example()Example B(3);/自動(dòng)調(diào)用構(gòu)造函數(shù)Example(int a)例:下面的程序創(chuàng)建了一個(gè)叫做date的類,它表示一個(gè)公歷日期。 #include #include class dateint day, month, year;public:date(char *d);date(int m, int d, int y);void show_date();date:date(cha

49、r *d) /用字符串初始化sscanf(d,”%d%*c%d%*c%d”,&month,&day,&year);date:date(int m, int d, int y)/用整數(shù)初始化day=d;month=m;year=y;void date:show_date()cout month ”/” day;cout ”/” year ”n”;main()date ob1(3,6,2000), ob2(”10/21/1999”);ob1.show_date();ob2.show_date();return 0;(5)派生類中的重載函數(shù) 在類繼承中,也可以出現(xiàn)基類的成員函數(shù)和派生類的成員函數(shù)名字

50、相同的情形。這時(shí),在派生類中說明的任何重載超越在基類中說明的函數(shù)。 #include class Aclassprivate:int aVal;public:Aclass() Aclass() int Value(int n) aVal = n+1; return aVal;class Bclassprivate:float bVal;public:int Value(float n) bVal = n+2; return bVal;int main()Bclass anob;cout anob.Value(100) n;return 0; 上例中,名為Bclass的類從Aclass類中派生出

51、來。Aclass 的定義中包含了一個(gè)名為Value的函數(shù)。 (6)作用域操作符 如果由派生類說明的成員函數(shù)超越了由基類說明的成員函數(shù),那么可以用作用域操作符(:)的指引來訪問在基類中說明的成員函數(shù)。 例:可以用下面的main()函數(shù)來代替上例中的main()函數(shù)。 int main() Bclass anobject; cout anobject.Aclass:Value(100) n; /使用作用域操作符來調(diào)用Aclass:Value() return 0;101運(yùn)行結(jié)果2操作符重載 操作符重載和函數(shù)重載功能一致。通過操作符重載,可以重新定義C+語言中的已有操作符的功能,使得它們能針對(duì)不同的

52、情況執(zhí)行不同的操作。操作符重載使得程序員可把C+操作符的定義擴(kuò)展到操作數(shù)是對(duì)象的情況。 (1)編寫操作符重載函數(shù) 函數(shù)類型 operator#(形參表) /函數(shù)體 其中,operator是關(guān)鍵字(所以有時(shí)也稱操作符重載函數(shù)為operator 函數(shù)),# 表示欲定義的操作符,函數(shù)類型指明返回值類型,通常與類類型一致或?yàn)関oid 類型。(2)操作符重載函數(shù)的作用域 當(dāng)重載一個(gè)操作符時(shí),普通的作用域規(guī)則也適用,操作符被重載的作用范圍就是重載它的函數(shù)出現(xiàn)的作用范圍。 Money operator+(int) /函數(shù)體 (3)C+如何實(shí)現(xiàn)操作符重載在C+語言中,操作符只能對(duì)屬于固有類型的常量和變量進(jìn)行操

53、作。而且,C語言中操作符的含義是固定的。在C+中你可以根據(jù)自己的意圖定義操作符。當(dāng)你重定義一個(gè)操作符時(shí),你可以用代碼記號(hào)來表達(dá)對(duì)用戶自定義類的操作。當(dāng)C+編譯程序?qū)σ粋€(gè)表達(dá)式進(jìn)行求值時(shí),它會(huì)檢查一系列的與操作符號(hào)混在一起的值(包括常量和變量)。當(dāng)遇到一個(gè)操作符時(shí),它首先判斷此操作符是用作一元或者是二元操作符。然后,編譯程序根據(jù)優(yōu)先規(guī)則和組織規(guī)則對(duì)此表達(dá)式求值,同時(shí)根據(jù)這些規(guī)則要求給操作符和操作數(shù)分組。編譯程序判定它遇到的操作符的操作數(shù)據(jù)的類型。只有在那時(shí),它才知道此表達(dá)式是否合法,而且如果合法,則應(yīng)當(dāng)產(chǎn)生什么代碼。例:重載一元操作符+,用來遞增Money類的值。例中Money類用來存放錢數(shù),它

54、包含兩個(gè)雙精度的成員變量。一個(gè)成員變量用于存儲(chǔ)結(jié)果的元值,另一個(gè)用于存儲(chǔ)結(jié)果的分值。#include #include #include #include class Money private:double dollars;double cents;public:Money() /定義構(gòu)造函數(shù)Money() /定義析構(gòu)函數(shù)Money(double d, double c);/另一構(gòu)造函數(shù)Money(double);/從double轉(zhuǎn)換Money operator+(); /操作符重載double GetAmount(double &n);Money Money:operator+()cent

55、s+;if(cents 99) dollars+;cents = 0;return *this;Money:Money(double d, double c)dollars = d; cents = c;Money:Money(double cash)/一個(gè)轉(zhuǎn)換構(gòu)造函數(shù) /將浮點(diǎn)值轉(zhuǎn)換成Money值double frac,n; frac = modf(cash,&n);/一個(gè)math.h函數(shù) cents = frac * 100; dollars = n;double Money:GetAmount(double &n)n=dollars;return cents;int main()doub

56、le c,d;Money myCash(7.99);c = myCash.GetAmount(d);cout d dollarsn;cout c centsn;+myCash;c = myCash.GetAmount(d);cout d dollarsn;cout c centsn;return 0;7 dollars99 cents8 dollars0 cents 運(yùn)行結(jié)果例:重載加法操作符,使其將兩個(gè)Money類的值相加并將結(jié)果存在一個(gè)Money對(duì)象中 。#include #include #include class Money private:double dollars;double

57、 cents;public:Money() /定義構(gòu)造函數(shù)Money() /定義析構(gòu)函數(shù)Money(double d, double c);/另一構(gòu)造函數(shù)Money(double);/轉(zhuǎn)換構(gòu)造函數(shù)Money operator+(Money m); /操作符重載double GetAmount(double &n);Money Money:operator+(Money m)cents += m.cents;dollars += m.dollars;if(cents 99) dollars = dollars +1; cents = cents-100;return *this;Money:Mo

58、ney(double d, double c)dollars = d; cents = c;Money:Money(double cash)/一個(gè)轉(zhuǎn)換構(gòu)造函數(shù)/將浮點(diǎn)值轉(zhuǎn)換成Money值double frac,n;frac = modf(cash,&n);/一個(gè)math.h函數(shù)cents = frac * 100;dollars = n;double Money:GetAmount(double &n)n=dollars;return cents;int main()double c,d;Money myCash(3.49);Money yourCash(50.86);myCash = myC

59、ash + yourCash;c = myCash.GetAmount(d);cout You now have d dollars.n;cout You also have c cents.n;return 0;You now have 54 dollars.You also have 35 cents. 運(yùn)行結(jié)果1多態(tài)性與虛擬函數(shù) C+的多態(tài)性是通過虛擬函數(shù)來實(shí)現(xiàn)的,而虛擬函數(shù)是基于繼承的環(huán)境中。在繼承關(guān)系下,派生類作為基類的子類,在任何要求基類對(duì)象的地方使用派生類對(duì)象是有意義的。我們可以用基類指針通過間接或直接的方式指向它的任何派生類的對(duì)象。當(dāng)通過一個(gè)基類指針引用一個(gè)派生類對(duì)象時(shí),只能調(diào)

60、用基類所定義的成員函數(shù),而無法調(diào)用派生類定義的成員函數(shù),即使派生類重新定義了基類的成員函數(shù),所調(diào)用的仍是基類中的而不是派生類中的成員函數(shù)。當(dāng)通過指針引用一個(gè)對(duì)象時(shí),指針的類型決定了可以調(diào)用的成員函數(shù)。 3.12 虛擬函數(shù)#include class Personpublic:void Display() cout “class Personn”;class Child:public Personpublic:void Display() cout ”class Childn”;class Old:public Personpublic:void Display() cout Display()

溫馨提示

  • 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)論