參考書:c/c++程序設(shè)計(jì)教程莺戒,龔沛增只损、楊志強(qiáng) 主編
本文主要內(nèi)容架構(gòu)如下圖:
1 概述
面向?qū)ο缶幊蹋∣bject Oriented Programming),面向?qū)ο蟮乃枷刖褪且鎸?duì)現(xiàn)實(shí)世界的實(shí)體,以對(duì)象為基本單位谅畅,分析、設(shè)計(jì)和實(shí)現(xiàn)一個(gè)系統(tǒng)。
基本概念:
- 對(duì)象
現(xiàn)實(shí)世界中的對(duì)象是各種各樣的實(shí)體薯定,可以是具體的或抽象的事物。每個(gè)對(duì)象皆有自己的特征瞳购、行為和作用在該對(duì)象上的活動(dòng)话侄。 - 類
許多對(duì)象具有相似的性質(zhì),執(zhí)行相同的操作,稱之為一類對(duì)象年堆。類是創(chuàng)建對(duì)象的模板吞杭,對(duì)象則是類的實(shí)例。 - 消息
在面向?qū)ο蟮某绦蛑斜渖ィ绦驁?zhí)行是對(duì)象之間傳遞消息完成的芽狗,消息傳遞一般由 接收消息的對(duì)象、所要觸發(fā)的方法和執(zhí)行此方法需要的參數(shù)組成的痒蓬。 - 方法
方法是某個(gè)對(duì)象接受了消息后采取的一系列操作的描述童擎。
2 類和對(duì)象
本節(jié)內(nèi)容如下:
2.1 類的定義
類定義的一般形式如下:
class 類名
{
public :
成員函數(shù)或數(shù)據(jù)的說(shuō)明;
private :
成員函數(shù)或數(shù)據(jù)的說(shuō)明攻晒;
protected :
成員函數(shù)或數(shù)據(jù)的說(shuō)明顾复;
};
各成員函數(shù)的實(shí)現(xiàn)鲁捏;
--類的定義包括說(shuō)明和實(shí)現(xiàn)兩部分芯砸。如果成員函數(shù)在說(shuō)明部分已經(jīng)給出定義,則在實(shí)現(xiàn)部分可以省略给梅;
--類的成員包含數(shù)據(jù)成員和函數(shù)成員假丧,自身類的對(duì)象不能作為自己的成員;
--private破喻,public虎谢,protected規(guī)定了成員如何被訪問(wèn),缺省時(shí)為private曹质;
--不涉及繼承時(shí)婴噩,protected 與private用法相同;
--類的數(shù)據(jù)成員不能在聲明時(shí)進(jìn)行初始化羽德,只能通過(guò)成員函數(shù)實(shí)現(xiàn)几莽;
--在類體外定義成員函數(shù)時(shí),格式為:
類名::函數(shù)名(參數(shù))
{
函數(shù)實(shí)現(xiàn)
}宅静;
2.2 對(duì)象的定義
定義對(duì)象
類名 對(duì)象名章蚣;
如:
class staff {......};
staff s,*p,s1[5];
//staff為已經(jīng)定義的類,s是一個(gè)對(duì)象姨夹,p是指向?qū)ο蟮闹羔樝舜梗瑂1為對(duì)象數(shù)組
對(duì)象的訪問(wèn)
- 一般對(duì)象成員:
對(duì)象名.數(shù)據(jù)成員名
對(duì)象名.函數(shù)成員名(參數(shù)) - 指針對(duì)象成員:
對(duì)象指針->數(shù)據(jù)成員
對(duì)象指針->函數(shù)成員(參數(shù))
或
(對(duì)象指針).數(shù)據(jù)成員
(對(duì)象指針).函數(shù)成員(參數(shù))
2.3 對(duì)象初始化
構(gòu)造函數(shù)
--與類名相同,不指定函數(shù)類型磷账;
--屬于成員函數(shù)峭沦,可以在類體內(nèi)或體外實(shí)現(xiàn);
--可以重載逃糟;
--在創(chuàng)建對(duì)象時(shí)自動(dòng)調(diào)用吼鱼,不能在程序中直接調(diào)用蓬豁,多用于初始化;
--用戶未定義時(shí)菇肃,系統(tǒng)會(huì)自動(dòng)生成缺省構(gòu)造函數(shù)地粪;
--用戶定義了構(gòu)造函數(shù),系統(tǒng)不會(huì)生成缺省構(gòu)造函數(shù)琐谤;
--若定義一個(gè)靜態(tài)對(duì)象而沒(méi)有初始化時(shí)蟆技,編譯器會(huì)將所有數(shù)據(jù)成員初始化為0.析構(gòu)函數(shù)
--在程序結(jié)束或使用對(duì)象的函數(shù)結(jié)束前會(huì)自動(dòng)調(diào)用,用于釋放對(duì)象笑跛;
--析構(gòu)函數(shù)名是在類名前加~付魔,無(wú)參數(shù),不需指定類型飞蹂;
--屬于成員函數(shù),可以在類體內(nèi)或體外定義翻屈;
--不能重載陈哑;
--可以由系統(tǒng)自動(dòng)調(diào)用,也可以在程序中調(diào)用伸眶;
--用戶未定義時(shí)惊窖,系統(tǒng)會(huì)自動(dòng)生成空的缺省析構(gòu)函數(shù)。拷貝初始化構(gòu)造函數(shù)
--用一個(gè)已知的對(duì)象來(lái)初始化一個(gè)被創(chuàng)建的同類對(duì)象厘贼;
--函數(shù)名與類名相同界酒,只有一個(gè)參數(shù),且該參數(shù)是對(duì)同類對(duì)象的引用嘴秸;
--如果用戶沒(méi)有定義拷貝初始化構(gòu)造函數(shù)毁欣,則系統(tǒng)會(huì)自動(dòng)生成,并將參數(shù)對(duì)象的全部數(shù)據(jù)值拷貝給正在創(chuàng)建的對(duì)象岳掐。
2.4 常對(duì)象和常成員
聲明常對(duì)象:
const 類名 對(duì)象名凭疮;
常對(duì)象中所有數(shù)據(jù)成員的值只能在構(gòu)造函數(shù)中初始化,不能被修改串述。
常函數(shù)成員
聲明常函數(shù)成員:
類型說(shuō)明符 函數(shù)名(參數(shù)) const
{......};
--只有常成員函數(shù)可以操作常對(duì)象执解;
--修改數(shù)據(jù)對(duì)象的函數(shù)不能聲明為常函數(shù);
常數(shù)據(jù)成員
聲明常數(shù)據(jù)成員:
const 數(shù)據(jù)類型 變量名纲酗;
--常數(shù)據(jù)成員不能被任何函數(shù)改動(dòng)衰腌;
--構(gòu)造函數(shù)只能通過(guò)初始化列表對(duì)其初始化,如:
class circle
{
private:
double x,y;
const double r;
public:
circle(double x1, double y1,double r1):r(re)
{
x=x1;y=y1;
}
}
2.5 靜態(tài)成員
希望一個(gè)成員能供所有對(duì)象共享時(shí)觅赊,可以設(shè)為靜態(tài)成員右蕊。
靜態(tài)數(shù)據(jù)成員
--靜態(tài)數(shù)據(jù)成員聲明時(shí)在前面加static;
--靜態(tài)數(shù)據(jù)成員是類的成員茉兰,不是對(duì)象的成員尤泽;
--初始化在類體外進(jìn)行,不加static和訪問(wèn)權(quán)限控制符。
//初始化格式:
數(shù)據(jù)類型 類名::靜態(tài)數(shù)據(jù)成員=值坯约;
//引用格式:
類名:靜態(tài)數(shù)據(jù)成員名
靜態(tài)函數(shù)成員
--聲明時(shí)在前面加static熊咽;
--靜態(tài)成員函數(shù)中可以直接引用靜態(tài)數(shù)據(jù)成員,對(duì)于非靜態(tài)數(shù)據(jù)成員闹丐,要通過(guò)對(duì)象引用横殴;
--除了可以像其他成員函數(shù)一樣引用,還可以如下引用:
類名::成員函數(shù)名(參數(shù))
2.6 友元函數(shù)
友元函數(shù)提供了一種非成員函數(shù)訪問(wèn)類的私有成員的方法卿拴,在一定情況下可以提高程序的執(zhí)行效率衫仑,但破壞了類的封裝和隱藏性。
--友元函數(shù)不是成員函數(shù)堕花,但要在類體內(nèi)說(shuō)明文狱;
--友元函數(shù)說(shuō)明時(shí),要在前面加friend缘挽,實(shí)現(xiàn)時(shí)不許加friend瞄崇;
--友元函數(shù)可以通過(guò)對(duì)象的方式訪問(wèn)類中的私有成員。
3 派生和繼承
繼承是軟件可重用性的一種形式壕曼,新類通過(guò)這種方式苏研,從現(xiàn)有的類中吸收其屬性和行為昂利,并對(duì)其覆蓋和改寫流部,產(chǎn)生新類所需要的功能。
本節(jié)內(nèi)容如下:
3.1 派生
通過(guò)繼承機(jī)制扰法,可以應(yīng)用現(xiàn)有類來(lái)定義新類轧飞。已經(jīng)存在的類稱為基類或父類衅鹿,由已存在的類派生的新類叫派生類或子類。
派生類擁有基類的成員踪少,也可以定義新成員塘安。
3.2 繼承
一個(gè)派生類可以由一個(gè)基類派生,稱為單繼承援奢;也可以由多個(gè)基類派生兼犯,稱為多繼承。
單繼承
-
派生類的定義
class 派生類名:繼承方式 基類名 { 派生類新成員定義 }集漾;
派生類的繼承方式
不同的繼承方式中切黔,派生類對(duì)基類成員的訪問(wèn)權(quán)限不同,如下:
基類 | 私有成員 | 公有成員 | 保護(hù)成員 |
---|---|---|---|
私有派生 | 不可訪問(wèn) | 私有成員 | 私有成員 |
公有派生 | 不可訪問(wèn) | 公有成員 | 保護(hù)成員 |
保護(hù)派生 | 不可訪問(wèn) | 保護(hù)成員 | 保護(hù)成員 |
--不論何種繼承方式具篇,基類的私有成員均不可被派生類及其成員函數(shù)訪問(wèn)纬霞;
--私有繼承時(shí),基類的公有成員和保護(hù)成員均成為派生類的私有成員驱显;
--公有繼承時(shí)诗芜,基類的公有成員和保護(hù)成員類型不變被繼承到派生類中瞳抓;
--保護(hù)繼承時(shí),基類的公有成員和保護(hù)成員均成為基類的保護(hù)成員伏恐;
--若基類的公用成員訪問(wèn)了基類的私有成員孩哑,則在派生類中不能使用,需要通過(guò)基類的方式調(diào)用翠桦。
-
派生類的構(gòu)造函數(shù)
定義派生類的構(gòu)造函數(shù)時(shí)横蜒,除了對(duì)自己的數(shù)據(jù)成員初始化,還需調(diào)用基類的構(gòu)造函數(shù)销凑。如果派生類中的成員含有基類對(duì)象丛晌,則還應(yīng)該對(duì)基類對(duì)象進(jìn)行初始化,例如:派生類構(gòu)造函數(shù)(初始化總參數(shù)表):基類構(gòu)造函數(shù)(參數(shù)表1)斗幼,基類對(duì)象名(參數(shù)表2) { 派生類中數(shù)據(jù)成員初始化 }
--調(diào)用順序:基類構(gòu)造函數(shù)——基類對(duì)象構(gòu)造函數(shù)——派生類構(gòu)造函數(shù)澎蛛;
--基類中有缺省的構(gòu)造函數(shù)或未定義時(shí),派生類構(gòu)造函數(shù)可以省略調(diào)用基類構(gòu)造函數(shù)蜕窿;
--若基類只包含有參數(shù)的構(gòu)造函數(shù)瓶竭,則在派生類中一定要調(diào)用。
#include <iostream>
using namespace std ;
class circle
{
private:
double x,y,r;
public:
void print() //const
{
cout<<"圓心:"<<x<<","<<y<<endl;
cout<<"半徑:"<<r<<endl;
cout<<"n:"<<n<<endl;
}
circle(double x1,double y1, double r1,int i1)
{
x=x1;y=y1;r=r1;i=i1;
}
circle()
{
};
class c:public circle
{
private:
int cd;
public :
c (int cd1,double x1,double y1, double r1,int i1 ):circle( x1, y1, r1, i1)
//注意基類構(gòu)造函數(shù)中沒(méi)有數(shù)據(jù)類型
{
cd=cd1;
}
void print()
{
circle::print();
//基類中的print函數(shù)訪問(wèn)了基類私有成員渠羞,在派生類中不能直接使用,需要通過(guò)基類調(diào)用
cout<<"cd:"<<cd<<endl;
}
};
int main(int argc, char** argv) {
circle p1(0,0,2,1);
c c1(1,2,3,4,5);
p1.print();
c1.print();
};
運(yùn)行結(jié)果:
-
派生類析構(gòu)函數(shù)
格式:~派生類名() {......};
系統(tǒng)先執(zhí)行派生類的析構(gòu)函數(shù)智哀,再執(zhí)行基類的析構(gòu)函數(shù)次询。
4 多態(tài)性
多態(tài)性是指同一個(gè)操作對(duì)于不同的對(duì)象會(huì)產(chǎn)生不同的反應(yīng)。函數(shù)重載和運(yùn)算符重載屬于靜態(tài)重載瓷叫,建立在虛函數(shù)上的多態(tài)性屬于動(dòng)態(tài)重載屯吊。
本節(jié)內(nèi)容如下:
4.1 函數(shù)重載
函數(shù)重載是指同一個(gè)函數(shù)名有不同的定義,定義重載函數(shù)時(shí)摹菠,要求參數(shù)至少有一個(gè)類型不同盒卸,或者個(gè)數(shù)不同,對(duì)返回值無(wú)要求次氨。
4.2 運(yùn)算符重載
運(yùn)算符重載原則
遵循函數(shù)重載的原則蔽介;
不能改變運(yùn)算符的優(yōu)先級(jí)和結(jié)合性,不改變其語(yǔ)法結(jié)構(gòu)煮寡。-
重載為類的成員函數(shù)
定義形式:
類名 operetor 運(yùn)算符(參數(shù)表)
調(diào)用形式:
對(duì)象1 運(yùn)算符 對(duì)象2
例如(程序待完善):class Str { private: char *s; ...... public: Str operator + (Str s1) //將+號(hào)重載為字符串拼接 { strcat(s, s1.s); Str result(s); return result; } }; void main() { Str s1,s2,s3; s3=s1+s2; }
重載為友元函數(shù)
(待補(bǔ)充)this指針
this是一個(gè)無(wú)需特殊定義的指針虹蓄,它隱含于每一個(gè)類的成員函數(shù)中,指向正在被某個(gè)成員函數(shù)操作的對(duì)象幸撕。
如果某個(gè)對(duì)象調(diào)用的成員函數(shù)薇组,則編譯程序首先將這個(gè)對(duì)象的地址賦給this指針,然后調(diào)用成員函數(shù)坐儿。
4.3 虛函數(shù)
虛函數(shù)是一種非靜態(tài)的成員函數(shù)律胀,反映了基類和派生類之間的特殊關(guān)系宋光,定義形式:
virtual 類型說(shuō)明符 函數(shù)名 (參數(shù)表)
如果在基類中,某個(gè)函數(shù)被聲明為虛函數(shù)炭菌,則在派生類中罪佳,該成員函數(shù)可能有其他的實(shí)現(xiàn)方法。
例子:
class Animal
{
public:
void character()
{
cout<<"動(dòng)物特征:不同"<<endl;
}
virtual void food()
{
cout<<"動(dòng)物食物:不同"<<endl;
}
};
class Giraffe:public Animal
{
public:
void character()
{
cout<<"長(zhǎng)頸鹿:長(zhǎng)脖子"<<endl;
}
virtual void food()
{
cout<<"食物:樹葉"<<endl;
}
};
class Elephent:public Animal
{
public:
void character()
{
cout<<"大象:長(zhǎng)鼻子"<<endl;
}
virtual void food()
{
cout<<"食物:草"<<endl;
}
};
void f(Animal &p)
{
p.character();
p.food();
}
void fg(Elephent &p)
{
p.character();
p.food();
}
int main()
{
Giraffe g;
f(g);
Elephent e;
fg(e);
return 0;
}
運(yùn)行結(jié)果:
在例程中娃兽,函數(shù)f的參數(shù)為基類指針菇民,主函數(shù)調(diào)用時(shí)傳入的為派生類的地址,此時(shí)投储,實(shí)際操作的是基類的成員函數(shù)第练,而對(duì)于虛函數(shù),則會(huì)根據(jù)派生類對(duì)象的地址執(zhí)行派生類中的函數(shù)玛荞。
虛函數(shù)的使用說(shuō)明:
--派生類中的虛函數(shù)應(yīng)與基類中的虛函數(shù)有相同的函數(shù)名娇掏、參數(shù)類型及個(gè)數(shù);
--派生類的虛函數(shù)可以不顯示聲明勋眯;
--只有虛函數(shù)操作的是對(duì)象的指針或?qū)ο蟮囊脮r(shí)婴梧,對(duì)該虛函數(shù)的調(diào)用采取的才是動(dòng)態(tài)聯(lián)編。
4.4 抽象類
含有純虛函數(shù)的類稱為抽象類客蹋。
純虛函數(shù)是指在基類中定義為空的虛函數(shù)塞蹭。
抽象類的性質(zhì):
--只能用作其他類的基類,不能建立其對(duì)象讶坯;
--不能用作參數(shù)類型和函數(shù)返回值類型番电;
--可以說(shuō)明指向抽象類指針引用,此指針可以指向其派生類辆琅。