国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++ 基礎(chǔ)教程:C++學(xué)習(xí)從零開始(五)

2020-05-23 14:25:07
字體:
供稿:網(wǎng)友

本文將說明自定義類型剩下的內(nèi)容,并說明各自的語義。

  權(quán)限

  成員函數(shù)的提供,使得自定義類型的語義從資源提升到了具有功能的資源。什么叫具有功能的資源?比如要把收音機(jī)映射為數(shù)字,需要映射的操作有調(diào)整收音機(jī)的頻率以接收不同的電臺;調(diào)整收音機(jī)的音量;打開和關(guān)閉收音機(jī)以防止電力的損耗。為此,收音機(jī)應(yīng)映射為結(jié)構(gòu),類似下面:

  struct Radiogram

  {

  double Frequency; /* 頻率 */ void TurnFreq( double value ); // 改變頻率

  float Volume; /* 音量 */ void TurnVolume( float value ); // 改變音量

  float Power; /* 電力 */ void TurnOnOff( bool bOn ); // 開關(guān)

  bool bPowerOn; // 是否開啟

  };

  上面的Radiogram::Frequency、Radiogram::Volume和Radiogram::Power由于定義為了結(jié)構(gòu)Radiogram的成員,因此它們的語義分別為某收音機(jī)的頻率、某收音機(jī)的音量和某收音機(jī)的電力。而其余的三個成員函數(shù)的語義也同樣分別為改變某收音機(jī)的頻率、改變某收音機(jī)的音量和打開或關(guān)閉某收音機(jī)的電源。注意這面的“某”,表示具體是哪個收音機(jī)的還不知道,只有通過成員操作符將左邊的一個具體的收音機(jī)和它們結(jié)合時才知道是哪個收音機(jī)的,這也是為什么它們被稱作偏移類型。這一點(diǎn)在下一篇將詳細(xì)說明。

  注意問題:為什么要將剛才的三個操作映射為結(jié)構(gòu)Radiogram的成員函數(shù)?因?yàn)槭找魴C(jī)具有這樣的功能?那么對于選西瓜、切西瓜和吃西瓜,難道要定義一個結(jié)構(gòu),然后給它定三個選、切、吃的成員函數(shù)??不是很荒謬嗎?前者的三個操作是對結(jié)構(gòu)的成員變量而言,而后者是對結(jié)構(gòu)本身而言的。那么改成吃快餐,吃快餐的漢堡包、吃快餐的薯?xiàng)l和喝快餐的可樂。如果這里的兩個吃和一個喝的操作變成了快餐的成員函數(shù),表示是快餐的功能?!這其實(shí)是編程思想的問題,而這里其實(shí)就是所謂的面向?qū)ο缶幊趟枷耄m然是很不錯的思想,但并不一定是合適的,下篇將詳細(xì)討論。

  上面我們之所以稱收音機(jī)的換臺是功能,是因?yàn)閷?shí)際中我們自己是無法直接改變收音機(jī)的頻率,必須通過旋轉(zhuǎn)選臺的那個旋鈕來改變接收的頻率,同樣,調(diào)音量也是通過調(diào)節(jié)音量旋鈕來實(shí)現(xiàn)的,而由于開機(jī)而導(dǎo)致的電力下降也不是我們直接導(dǎo)致,而是間接通過收聽電臺而導(dǎo)致的。因此上面的Radiogram::Power、Radiogram::Frequency等成員變量都具有一個特殊特性--外界,這臺收音機(jī)以外的東西是無法改變它們的。為此,C++提供了一個語法來實(shí)現(xiàn)這種語義。在類型定義符中,給出這樣的格式:<權(quán)限>:。這里的<權(quán)限>為public、protected和private中的一個,分別稱作公共的、保護(hù)的和私有的,如下:

  class Radiogram

  {

  protected: double m_Frequency; float m_Volume; float m_Power;

  private: bool m_bPowerOn;

  public: void TurnFreq( double ); void TurnVolume( float ); void TurnOnOff

  ( bool );

  };

  

  可以發(fā)現(xiàn),它和之前的標(biāo)號的定義格式相同,但并不是語句修飾符,即可以struct ABC{ private: };。這里不用非要在private:后面接語句,因?yàn)樗皇钦Z句修飾符。從它開始,直到下一個這樣的語法,之間所有的聲明和定義而產(chǎn)生的成員變量或成員函數(shù)都帶有了它所代表的語義。比如上面的類Radiogram,其中的Radiogram::m_Frequency、Radiogram::m_Volume和Radiogram::m_Power是保護(hù)的成員變量,Radiogram::m_bPowerOn是私有的成員變量,而剩下的三個成員函數(shù)都是公共的成員函數(shù)。注意上面的語法是可以重復(fù)的,如:struct ABC { public: public: long a; private: float b; public: char d; };。

  什么意思?很簡單,公共的成員外界可以訪問,保護(hù)的成員外界不能訪問,私有的成員外界及子類不能訪問。關(guān)于子類后面說明。先看公共的。對于上面。

  如下將報錯:

  Radiogram a; a.m_Frequency = 23.0; a.m_Power = 1.0f; a.m_bPowerOn = true;

  因?yàn)樯厦鎸的三次操作都使用了a的保護(hù)或私有成員,編譯器將報錯,因?yàn)檫@兩種成員外界是不能訪問的。而a.TurnFreq( 10 );就沒有任何問題,因?yàn)槌蓡T函數(shù)Radiogram::TurnFreq是公共成員,外界可以訪問。那么什么叫外界?對于某個自定義類型,此自定義類型的成員函數(shù)的函數(shù)體內(nèi)以外的一切能寫代碼的地方都稱作外界。因此,對于上面的Radiogram,只有它的三個成員函數(shù)的函數(shù)體內(nèi)可以訪問它的成員變量。即下面的代碼將沒有問題。

  void Radiogram::TurnFreq( double value ) { m_Frequency += value; }

  因?yàn)閙_Frequency被使用的地方是在Radiogram::TurnFreq的函數(shù)體內(nèi),不屬于外界。

  為什么要這樣?表現(xiàn)最開始說的語義。首先,上面將成員定義成public或private對于最終生成的代碼沒有任何影響。然后,我之前說的調(diào)節(jié)接收頻率是通過調(diào)節(jié)收音機(jī)里面的共諧電容的容量來實(shí)現(xiàn)的,這個電容的容量人必須借助元件才能做到,而將接收頻率映射成數(shù)字后,由于是數(shù)字,則CPU就能修改。如果直接a.m_Frequency += 10;進(jìn)行修改,就代碼上的意義,其就為:執(zhí)行這個方法的人將收音機(jī)的接收頻率增加10KHz,這有違我們的客觀世界,與前面的語義不合。因此將其作為語法的一種提供,由編譯器來進(jìn)行審查,可以讓我們編寫出更加符合我們所生活的世界的語義的代碼。

  應(yīng)注意可以union ABC { long a; private: short b; };。這里的ABC::a之前沒有任何修飾,那它是public還是protected?相信從前面舉的那么多例子也已經(jīng)看出,應(yīng)該是public,這也是為什么我之前一直使用struct和union來定義自定義類型,否則之前的例子都將報錯。而前篇說過結(jié)構(gòu)和類只有一點(diǎn)很小的區(qū)別,那就是當(dāng)成員沒有進(jìn)行修飾時,對于類,那個成員將是private而不是public,即如下將錯誤。

  class ABC { long a; private: short b; }; ABC a; a.a = 13;

  ABC::a由于前面的class而被看作private。就從這點(diǎn),可以看出結(jié)構(gòu)用于映射資源(可被直接使用的資源),而類用于映射具有功能的資源。下篇將詳細(xì)討論它們在語義上的差別。

  構(gòu)造和析構(gòu)

  了解了上面所提的東西,很明顯就有下面的疑問:

  struct ABC { private: long a, b; }; ABC a = { 10, 20 };

  上面的初始化賦值變量a還正確嗎?當(dāng)然錯誤,否則在語法上這就算一個漏洞了(外界可以借此修改不能修改的成員)。但有些時候的確又需要進(jìn)行初始化以保證一些邏輯關(guān)系,為此C++提出了構(gòu)造和析構(gòu)的概念,分別對應(yīng)于初始化和掃尾工作。在了解這個之前,讓我們先看下什么叫實(shí)例(Instance)。

  實(shí)例是個抽象概念,表示一個客觀存在,其和下篇將介紹的“世界”這個概念聯(lián)系緊密。比如:“這是桌子”和“這個桌子”,前者的“桌子”是種類,后者的“桌子”是實(shí)例。這里有10只羊,則稱這里有10個羊的實(shí)例,而羊只是一種類型。可以簡單地將實(shí)例認(rèn)為是客觀世界的物體,人類出于方便而給各種物體分了類,因此給出電視機(jī)的說明并沒有給出電視機(jī)的實(shí)例,而拿出一臺電視機(jī)就是給出了一個電視機(jī)的實(shí)例。同樣,程序的代碼寫出來了意義不大,只有當(dāng)它被執(zhí)行時,我們稱那個程序的一個實(shí)例正在運(yùn)行。如果在它還未執(zhí)行完時又要求操作系統(tǒng)執(zhí)行了它,則對于多任務(wù)操作系統(tǒng),就可以稱那個程序的兩個實(shí)例正在被執(zhí)行,如同時點(diǎn)開兩個Word文件查看,則有兩個Word程序的實(shí)例在運(yùn)行。

  

  在C++中,能被操作的只有數(shù)字,一個數(shù)字就是一個實(shí)例(這在下篇的說明中就可以看出),更一般的,稱標(biāo)識記錄數(shù)字的內(nèi)存的地址為一個實(shí)例,也就是稱變量為一個實(shí)例,而對應(yīng)的類型就是上面說的物體的種類。比如:long a, *pA = &a, &ra = a;,這里就生成了兩個實(shí)例,一個是long的實(shí)例,一個是long*的實(shí)例(注意由于ra是long&所以并未生成實(shí)例,但ra仍然是一個實(shí)例)。同樣,對于一個自定義類型,如:Radiogram ab, c[3];,則稱生成了四個Radiogram的實(shí)例。

  對于自定義類型的實(shí)例,當(dāng)其被生成時,將調(diào)用相應(yīng)的構(gòu)造函數(shù);當(dāng)其被銷毀時,將調(diào)用相應(yīng)的析構(gòu)函數(shù)。誰來調(diào)用?編譯器負(fù)責(zé)幫我們編寫必要的代碼以實(shí)現(xiàn)相應(yīng)構(gòu)造和析構(gòu)的調(diào)用。構(gòu)造函數(shù)的原型(即函數(shù)名對應(yīng)的類型,如float AB( double, char );的原型是float( double, char ))的格式為:直接將自定義類型的類型名作為函數(shù)名,沒有返回值類型,參數(shù)則隨便。對于析構(gòu)函數(shù),名字為相應(yīng)類型名的前面加符號“~”,沒有返回值類型,必須沒有參數(shù)。

  如下:

  struct ABC { ABC(); ABC( long, long );

  ~ABC(); bool Do( long );

  long a, count; float *pF; };

  ABC::ABC() { a = 1; count = 0; pF = 0; }

  ABC::ABC( long tem1, long tem2 )

  { a = tem1; count = tem2; pF = new float[ count ]; }

  ABC::~ABC() { delete[] pF; }

  bool ABC::Do( long cou )

  {

  float *p = new float[ cou ];

  if( !p )

  return false;

  delete[] pF;

  pF = p;

  count = cou;

  return true;

  }

  extern ABC g_ABC;

  void main(){ ABC a, &r = a; a.Do( 10 );

  { ABC b( 10, 30 ); }

  ABC *p = new ABC[10];

  delete[] p; }

  ABC g_a( 10, 34 ), g_p = new ABC[5];

  上面的結(jié)構(gòu)ABC就定義了兩個構(gòu)造函數(shù)(注意是兩個重載函數(shù)),名字都為ABC::ABC(實(shí)際將由編譯器轉(zhuǎn)成不同的符號以供連接之用)。也定義了一個析構(gòu)函數(shù)(注意只能定義一個,因?yàn)槠浔仨殯]有參數(shù),也就無法進(jìn)行重載了),名字為ABC::~ABC。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 舒兰市| 南阳市| 错那县| 南涧| 平潭县| 湘阴县| 丽江市| 潮安县| 苗栗市| 梁山县| 融水| 察隅县| 景宁| 高清| 天镇县| 新竹市| 西贡区| 青铜峡市| 溆浦县| 汶上县| 广宗县| 遵义县| 福清市| 紫阳县| 昆山市| 清新县| 繁峙县| 廉江市| 铜川市| 昌邑市| 马山县| 含山县| 米脂县| 焦作市| 德清县| 麻栗坡县| 兴宁市| 库尔勒市| 肇源县| 乐平市| 平武县|