2020-02-14 C++核心編程03-基本框架

4.2.8靜態(tài)成員

靜態(tài)成員變量

1.所有對(duì)象共享同一份數(shù)據(jù)贤壁;

2.在編譯階段分配內(nèi)存;

3.類內(nèi)聲明,類外初始化;

示例:

class Person

{

public:

public:

static int _A;

//靜態(tài)成員變量颠通,不屬于某個(gè)對(duì)象上,所有對(duì)象都共享同一個(gè)數(shù)據(jù)

//靜態(tài)成員變量具有兩種訪問(wèn)方式

//1.通過(guò)對(duì)象進(jìn)行訪問(wèn)

//2.通過(guò)類名進(jìn)行訪問(wèn)

//靜態(tài)成員變量也是有訪問(wèn)權(quán)限的

private:

static int _B;//類內(nèi)聲明

};

int Person::_A=100;

int Person::_B = 200;//類外初始化

void test02()

{

//通過(guò)類名訪問(wèn)靜態(tài)成員變量

cout << Person::_A << endl;

//cout << Person::_B << endl;類外訪問(wèn)不到私有(保護(hù))靜態(tài)成員變量

}

靜態(tài)成員函數(shù)

1.所有對(duì)象共享同一個(gè)函數(shù)膀懈;

2.靜態(tài)成員函數(shù)只能訪問(wèn)靜態(tài)成員變量顿锰;

示例:

class Person

{

public:

static void func()//靜態(tài)成員函數(shù)也是有訪問(wèn)權(quán)限的

{

_A = 100;//靜態(tài)成員函數(shù)可以訪問(wèn) 靜態(tài)成員變量

//_B = 200;//靜態(tài)成員函數(shù)不可以訪問(wèn) 非靜態(tài)成員變量

? ? ? ? //因?yàn)闊o(wú)法區(qū)分到底是哪個(gè)對(duì)象的_B

cout << "static void func()" << endl;

}

public:

static int _A;

int _B;

private:

static void func2()

{

cout << "static void func2()" << endl;

}

};

int Person::_A = 0;

void test01()

{

Person p;

p.func();//1.通過(guò)對(duì)象訪問(wèn)

cout << "-------" << endl;

Person::func();//2.通過(guò)類名訪問(wèn)

}

void test02()

{

//Person::func2();//類外訪問(wèn)不到私有的靜態(tài)成員函數(shù)

}

4.3C++對(duì)象模型和this指針

4.3.1成員變量和成員函數(shù)分開(kāi)存儲(chǔ)

只有非靜態(tài)成員變量才屬于類的對(duì)象上

4.3.1this指針

每個(gè)非靜態(tài)成員函數(shù)只會(huì)誕生一份函數(shù)實(shí)例,也就是說(shuō)多個(gè)同類型的對(duì)象會(huì)共用一塊代碼

C++通過(guò)提供特殊的對(duì)象指針,this指針撵儿,能夠使得代碼區(qū)分調(diào)用自己的對(duì)象

概念:

1.this指針指向被調(diào)用的成員函數(shù)所屬的對(duì)象乘客;

2.this指針是隱含每一個(gè)非靜態(tài)成員函數(shù)的一種指針;

3.this指針不需要定義淀歇,直接使用即可;

用途:

1.當(dāng)形參和成員變量同名時(shí)匈织,可用this指針來(lái)區(qū)分浪默;(解決名稱沖突)

2.在類的非靜態(tài)成員函數(shù)中返回對(duì)象本身,可使用 return *this缀匕;

示例:

class Person

{

public:

Person(int age)

{

//1.解決名稱沖突

//age = age;//error 纳决,編譯器認(rèn)為兩個(gè)age是同一個(gè),即形參age

//this指針指向的是被調(diào)用成員函數(shù)所屬的對(duì)象

this->age = age;

}

void PersonAddAge(Person &p)

{

this->age += p.age;

}

//易錯(cuò)點(diǎn)

//Person PersonAddAge2(Person &p)

//error

Person & PersonAddAge2(Person &p)

{

this->age += p.age;

//this是指向p2的指針乡小,而*this就是p2這個(gè)對(duì)象本體

return *this;

}

Person? PersonAddAge3(Person &p)

{

this->age += p.age;

//this是指向p2的指針阔加,而*this就是p2這個(gè)對(duì)象本體

return *this;

}

int age;

};

void test01()

{

Person p1(18);

cout << "the age of p1 is " << p1.age << endl;

}

//2.返回對(duì)象本身用*this

void test02()

{

Person p1(10);

Person p2(10);

p2.PersonAddAge(p1);

cout << "the age of p2 is " << p2.age << endl;

//p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);

//error

}

void test03()

{

Person p1(10);

Person p2(10);

p2.PersonAddAge2(p1);

cout << "the age of p2 is " << p2.age << endl;

//鏈?zhǔn)骄幊趟枷?/p>

p2.PersonAddAge2(p1).PersonAddAge2(p1).PersonAddAge2(p1);

cout << "the age of p2 is " << p2.age << endl;

}

void test04()

{

Person p1(10);

Person p2(10);

p2.PersonAddAge3(p1);//p2.age更改,但函數(shù)返回的是p2的拷貝

? ? ? ? ? ? ? ? ? ? //此時(shí)p2.age=20

cout << "the age of p2 is " << p2.age << endl;

//第一個(gè)函數(shù)更改了p2.age 但返回的是p2的拷貝 記為 p2’

//第二個(gè)函數(shù)更改的是p2’

//第三個(gè)函數(shù)更改的是p2''

//所以p2.age=30

p2.PersonAddAge3(p1).PersonAddAge3(p1).PersonAddAge3(p1);

cout << "the age of p2 is " << p2.age << endl;

}

4.3.3空指針訪問(wèn)成員函數(shù)

C++中空指針也可以調(diào)用成員函數(shù)满钟,但要注意有沒(méi)有用到this指針

如果用到this指針胜榔,需要加以判斷保證代碼健壯性

示例:

class Person

{

public:

//空指針可以正常訪問(wèn)

void showClassName()

{

cout << "this is Person class" << endl;

}

void showPersonAge()

{

//報(bào)錯(cuò)原因是因?yàn)閭魅氲闹羔槥镹ULL

cout << "age is " << m_Age << endl;

//m_Age默認(rèn)為this->m_Age

}

void showPersonAge2()

{

//提高代碼健壯性

if (this == NULL)

{

return;

}

cout << "age is " << m_Age << endl;

}

int m_Age;

};

void test01()

{

Person *p = NULL;

p->showClassName();

//p->showPersonAge();

//error

p->showPersonAge2();

}

4.3.4const修飾成員函數(shù)

常函數(shù):

1.成員函數(shù)后加const后我們稱這個(gè)函數(shù)為常函數(shù);

2.常函數(shù)內(nèi)不可以修改成員屬性湃番;

3.成員屬性聲明時(shí)加關(guān)鍵字mutable后夭织,在常函數(shù)中依然可以修改

常對(duì)象:

1.聲明對(duì)象前加const稱該對(duì)象為常對(duì)象;

2.常對(duì)象只能調(diào)用常函數(shù)吠撮;

示例:

class Person

{

public:

void showPerson1()

{

//this指針本質(zhì)是指針常量尊惰,指針的指向是不可以修改的

//Person * const this;

this->m_A = 100;//this指針指向的內(nèi)容可以修改

//this = NULL;//this指針不可以修改指針指向

}

//在成員函數(shù)后面加上const 修飾的是this指針,讓指針指向的值也不可以修改

void showPerson2() const? //常函數(shù)

{

//如果想要this指針指向的值也不可以修改

//把const加在成員函數(shù)后

//就相當(dāng)于const Person * const this;

? ? //this->m_A = 100;//error

this->m_B = 100;//ok

}

public:

int m_A;

mutable int m_B;//特殊變量泥兰,即使在常函數(shù)中弄屡,也可以修改這個(gè)值

? ? ? ? ? ? ? ? //加關(guān)鍵字mutable

};

void test01()

{

//常對(duì)象

const Person p;

//p.m_A = 100;//error

p.m_B = 100;//ok ,m_B是特殊值,在常對(duì)象下也可以修改

? ? //常對(duì)象只能調(diào)用常函數(shù)

//不可以調(diào)用普通成員函數(shù)鞋诗,因?yàn)槠胀ǔ蓡T函數(shù)可以修改屬性

//p.showPerson1();//error

p.showPerson2();//ok

}


4.4友元

目的:讓一個(gè)函數(shù)或類 訪問(wèn)另一個(gè)類中的私有成員

關(guān)鍵字:friend

友元的三種實(shí)現(xiàn):

1.全局函數(shù)做友元函數(shù)

2.類做友元類

3.類的成員函數(shù)做友元

4.5運(yùn)算符重載

概念:對(duì)已有的運(yùn)算符重新進(jìn)行定義膀捷,賦予其另一種功能,以適應(yīng)不同的數(shù)據(jù)類型

4.5.1加號(hào)運(yùn)算符重載

作用:實(shí)現(xiàn)兩個(gè)自定義數(shù)據(jù)類型相加的運(yùn)算

兩種方式:

1.成員函數(shù)重載

2.全局函數(shù)重載

示例:

class Person

{

public:

//Person operator+(Person &p);//1.成員函數(shù)重載

Person(){}

Person(int a, int b);

public:

int m_A;

int m_B;

};

//Person Person::operator+(Person &p)

//{

// Person temp;

// temp.m_A=this->m_A + p.m_A;

// temp.m_B=this->m_B + p.m_B;

// return temp;

//}

Person::Person(int a, int b)

{

m_A = a;

m_B = b;

}

//2.全局函數(shù)重載

Person operator+(Person &p1, Person &p2)

{

Person temp;

temp.m_A = p1.m_A + p2.m_A;

temp.m_B = p1.m_B + p2.m_B;

return temp;

}

//運(yùn)算符重載师脂,也可以發(fā)生函數(shù)重載

//函數(shù)重載的版本

Person operator+(Person &p1, int a)

{

Person temp;

temp.m_A = p1.m_A + a;

temp.m_B = p1.m_B + a;

return temp;

}

void test00()

{

Person p1(10, 10);

Person p2 = p1 + 10;

cout << "p2.m_A=" << p2.m_A << endl

<< "p2.m_B=" << p2.m_B << endl;

}

void test01()

{

Person p1(10, 10);

Person p2(20, 20);

Person p3 = p1 + p2;

//1.成員函數(shù)重載的本質(zhì)調(diào)用

//Person p3=p1.operator+(p2);

//2.全局函數(shù)重載的本質(zhì)調(diào)用

//Person p3=operator+(p1,p2);

}

總結(jié):

1.對(duì)于內(nèi)置的數(shù)據(jù)類型的表達(dá)式的運(yùn)算符是不可能改變的担孔;

2.不要濫用運(yùn)算符重載;

4.5.2左移運(yùn)算符重載

作用:輸出自定義數(shù)據(jù)類型

注意:只能通過(guò)全局函數(shù)重載輸出流運(yùn)算符吃警,且需要設(shè)置為類的友元函數(shù)

示例:

class Person

{

//將全局函數(shù)設(shè)置為友元

friend ostream & operator<<(ostream &os, Person &p);

public:

//利用成員函數(shù)重載 左移運(yùn)算符 p.operator<<(cout) 簡(jiǎn)化版本 p<<cout

//不會(huì)利用成員函數(shù)重載<<運(yùn)算符 糕篇,因?yàn)闊o(wú)法實(shí)現(xiàn)cout在左側(cè)

//void operator<<(cout ){}

? ? Person(int a, int b)

{

m_A = a;

m_B = b;

}

private:

int m_A;

int m_B;

};

//只能利用全局函數(shù)重載左移運(yùn)算符

//void? operator<<(ostream &cout,Person &p)//本質(zhì) operator<<(cout,p) 簡(jiǎn)化 cout<<p

//{

// cout << "m_A=" << p.m_A << endl

// << "m_B=" << p.m_B << endl;

//}

//ostream 也是一種類

//ostream對(duì)象只能有一個(gè),所以需要加&

ostream & operator<<(ostream &os, Person &p)//本質(zhì) operator<<(cout,p) 簡(jiǎn)化 cout<<p

{

os << "m_A=" << p.m_A <<"? "

<< "m_B=" << p.m_B ;

return os;

}

void test01()

{

Person p(10,10);

//cout << p ;

cout<<p<<endl;

//返回值為void時(shí)酌心,上一行程序會(huì)崩掉

//由于左側(cè)返回的是void 拌消,不能實(shí)現(xiàn)鏈?zhǔn)骄幊?/p>

//因此需要對(duì)左移運(yùn)算符重載函數(shù)進(jìn)行返回值的修改

}

總結(jié):重載左移運(yùn)算符配合友元可以實(shí)現(xiàn)輸出自定義數(shù)據(jù)類型

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子墩崩,更是在濱河造成了極大的恐慌氓英,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹦筹,死亡現(xiàn)場(chǎng)離奇詭異铝阐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)铐拐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門徘键,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人遍蟋,你說(shuō)我怎么就攤上這事吹害。” “怎么了虚青?”我有些...
    開(kāi)封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵它呀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我棒厘,道長(zhǎng)纵穿,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任绊谭,我火速辦了婚禮政恍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘达传。我一直安慰自己篙耗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布宪赶。 她就那樣靜靜地躺著宗弯,像睡著了一般搂妻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上欲主,一...
    開(kāi)封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音扁瓢,去河邊找鬼宰掉。 笑死鞠值,一個(gè)胖子當(dāng)著我的面吹牛嘱丢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼叽掘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了更扁?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤疯潭,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后面殖,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哭廉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年脊僚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遵绰。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辽幌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出椿访,到底是詐尸還是另有隱情乌企,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布成玫,位于F島的核電站加酵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏哭当。R本人自食惡果不足惜猪腕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钦勘。 院中可真熱鬧陋葡,春花似錦、人聲如沸彻采。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肛响。三九已至岭粤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間终惑,已是汗流浹背绍在。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人偿渡。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓臼寄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親溜宽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吉拳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容