面向?qū)ο蟪绦蛟O(shè)計(jì)10-1.其他_第1頁
面向?qū)ο蟪绦蛟O(shè)計(jì)10-1.其他_第2頁
面向?qū)ο蟪绦蛟O(shè)計(jì)10-1.其他_第3頁
面向?qū)ο蟪绦蛟O(shè)計(jì)10-1.其他_第4頁
面向?qū)ο蟪绦蛟O(shè)計(jì)10-1.其他_第5頁
已閱讀5頁,還剩38頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、面向?qū)ο蟪绦蛟O(shè)計(jì)面向?qū)ο蟪绦蛟O(shè)計(jì)十、其他十、其他n嵌套類嵌套類n類型轉(zhuǎn)換類型轉(zhuǎn)換n在一個(gè)類的內(nèi)部定義另一個(gè)類,稱之為嵌套類在一個(gè)類的內(nèi)部定義另一個(gè)類,稱之為嵌套類(nested class)(nested class),或嵌套類型,或嵌套類型(nested type)(nested type)。n之所以引入這樣一個(gè)嵌套類,往往是因?yàn)橥鈬愔砸脒@樣一個(gè)嵌套類,往往是因?yàn)橥鈬愋枰褂们短最悓ο笞鳛榈讓訉?shí)現(xiàn),并且該嵌套需要使用嵌套類對象作為底層實(shí)現(xiàn),并且該嵌套類只用于外圍類的實(shí)現(xiàn)。通過嵌套類機(jī)制,可以類只用于外圍類的實(shí)現(xiàn)。通過嵌套類機(jī)制,可以對用戶隱藏該嵌套類的實(shí)現(xiàn),減少全局的標(biāo)識(shí)符對用戶隱

2、藏該嵌套類的實(shí)現(xiàn),減少全局的標(biāo)識(shí)符,限制用戶使用該類建立對象。,限制用戶使用該類建立對象。第10章其他2022-6-284n嵌套類是其外圍類的一個(gè)成員,像其他任何成員嵌套類是其外圍類的一個(gè)成員,像其他任何成員一樣,外圍類決定對這個(gè)類型的訪問,在外圍類一樣,外圍類決定對這個(gè)類型的訪問,在外圍類的的publicpublic部分定義的嵌套類是可在任何地方使用部分定義的嵌套類是可在任何地方使用的類型,在的類型,在protectedprotected部分的嵌套類是只能由外部分的嵌套類是只能由外圍類、友元或派生類訪問的類型,在圍類、友元或派生類訪問的類型,在privateprivate部部分的嵌套類是只能

3、由外圍類、友元訪問的類型。分的嵌套類是只能由外圍類、友元訪問的類型。n嵌套類的名字在其外圍類的作用域中是可見的,嵌套類的名字在其外圍類的作用域中是可見的,但是在其他類域或名字空間中是不可見的,這意但是在其他類域或名字空間中是不可見的,這意味著嵌套類的名字不會(huì)與另一作用域中聲明的相味著嵌套類的名字不會(huì)與另一作用域中聲明的相同名字沖突。同名字沖突。n雖然嵌套類在外圍類內(nèi)部定義,但它是一個(gè)獨(dú)立雖然嵌套類在外圍類內(nèi)部定義,但它是一個(gè)獨(dú)立的類,基本上與外圍類不相關(guān)。它的成員不屬于的類,基本上與外圍類不相關(guān)。它的成員不屬于外圍類,外圍類的成員也不屬于該嵌套類。嵌套外圍類,外圍類的成員也不屬于該嵌套類。嵌套

4、類的出現(xiàn)只是告訴外圍類有一個(gè)這樣的類型成員類的出現(xiàn)只是告訴外圍類有一個(gè)這樣的類型成員供外圍類使用。供外圍類使用。n外圍類對嵌套類成員的訪問沒有任何特權(quán),嵌套外圍類對嵌套類成員的訪問沒有任何特權(quán),嵌套類對外圍類成員的訪問也同樣如此,它們都遵循類對外圍類成員的訪問也同樣如此,它們都遵循普通類的訪問權(quán)限控制規(guī)則。普通類的訪問權(quán)限控制規(guī)則。n嵌套類可以直接引用外圍類的靜態(tài)成員、類型名嵌套類可以直接引用外圍類的靜態(tài)成員、類型名和枚舉成員,即使這些是和枚舉成員,即使這些是privateprivate的。的。第10章其他2022-6-286n嵌套類一般定義在外圍類的類體內(nèi)。嵌套類的成嵌套類一般定義在外圍類的

5、類體內(nèi)。嵌套類的成員函數(shù)可以其類體內(nèi)定義,也可以在其類體外定員函數(shù)可以其類體內(nèi)定義,也可以在其類體外定義,但必須在外圍類的同一作用域中,且要用外義,但必須在外圍類的同一作用域中,且要用外圍類進(jìn)行限定。圍類進(jìn)行限定。n嵌套類也可在外圍類外或另一個(gè)頭文件中定義,嵌套類也可在外圍類外或另一個(gè)頭文件中定義,并在外圍類中前向聲明這個(gè)嵌套類即可。當(dāng)然,并在外圍類中前向聲明這個(gè)嵌套類即可。當(dāng)然,在外圍類外面定義這個(gè)嵌套類時(shí),應(yīng)該使用外圍在外圍類外面定義這個(gè)嵌套類時(shí),應(yīng)該使用外圍類進(jìn)行限定。如果在另一個(gè)頭文件中定義,使用類進(jìn)行限定。如果在另一個(gè)頭文件中定義,使用時(shí),只需要在外圍類的實(shí)現(xiàn)文件中包含這個(gè)頭文時(shí),只

6、需要在外圍類的實(shí)現(xiàn)文件中包含這個(gè)頭文件即可。件即可。第10章其他2022-6-287n比較好的設(shè)計(jì)是把嵌套類定義為外圍類的私有成比較好的設(shè)計(jì)是把嵌套類定義為外圍類的私有成員,避免該嵌套類可以在整個(gè)程序中員,避免該嵌套類可以在整個(gè)程序中( (在外圍類在外圍類的友元和成員定義之外的友元和成員定義之外) )用作類型。有了這個(gè)方用作類型。有了這個(gè)方法,我們把嵌套類的所有成員都聲明為公有的也法,我們把嵌套類的所有成員都聲明為公有的也不再有任何壞處,因?yàn)橹挥型鈬惖挠言统蓡T不再有任何壞處,因?yàn)橹挥型鈬惖挠言统蓡T 可以訪問嵌套類的成員。我們也不需要在嵌套類可以訪問嵌套類的成員。我們也不需要在嵌套類中對

7、外圍類進(jìn)行友元聲明了。中對外圍類進(jìn)行友元聲明了。第10章其他2022-6-288/示例嵌套類定義示例嵌套類定義class List class List public:public:/ ./ .private:private:class ListItemclass ListItem / / 它的成員都是公有的它的成員都是公有的public:public:ListItem( int valListItem( int val = 0 ); = 0 );ListItemListItem * *next;next;intint value; value;ListItemListItem * *list

8、;list;ListItem ListItem * *at_endat_end; ;第10章其他2022-6-289/ / 用外圍類名限定修飾嵌套類名用外圍類名限定修飾嵌套類名List:ListItem:List:ListItem:ListItem( int valListItem( int val ) ) value = valvalue = val; ;next = 0;next = 0; n 當(dāng)我們沒有在嵌套類體內(nèi)以當(dāng)我們沒有在嵌套類體內(nèi)以inline inline 形式定義嵌套類的形式定義嵌套類的成員函數(shù)時(shí),我們就必須在最外圍的類之外定義這些成成員函數(shù)時(shí),我們就必須在最外圍的類之外定義

9、這些成員函數(shù),并員函數(shù),并用外圍類名限定修飾嵌套類名用外圍類名限定修飾嵌套類名。第10章其他2022-6-2810n在嵌套類的定義被看到之前,我們只能聲明嵌套在嵌套類的定義被看到之前,我們只能聲明嵌套類的指針和引用。類的指針和引用。class List class List public:public:/ ./ .private:private:/ / 這個(gè)聲明是必需的這個(gè)聲明是必需的class ListItemclass ListItem; ;ListItemListItem * *list;list;ListItem at_endListItem at_end; /; /錯(cuò)誤錯(cuò)誤: : 未

10、定義嵌套類未定義嵌套類ListItemListItem;第10章其他2022-6-2811n嵌套類不能直接訪問其外圍類的非靜態(tài)成員,即嵌套類不能直接訪問其外圍類的非靜態(tài)成員,即使這些成員是公有的,任何對外圍類的非靜態(tài)成使這些成員是公有的,任何對外圍類的非靜態(tài)成員的訪問都要求通過外圍類的指針,引用或?qū)ο髥T的訪問都要求通過外圍類的指針,引用或?qū)ο髞硗瓿伞@纾簛硗瓿?。例如:?0章其他2022-6-2812class List class List public:public:int init( intint init( int ); );private:private:class ListIte

11、mclass ListItem public:public:ListItem( int valListItem( int val = 0 ); = 0 );void mf( const List & );void mf( const List & );intint value; value;int membint memb; ;List:ListItem:ListItem( int valList:ListItem:ListItem( int val ) ) / List:init/ List:init() () 是類是類 List List 的非靜態(tài)成員的非靜態(tài)成員value

12、 = init( valvalue = init( val ); / ); / 錯(cuò)誤錯(cuò)誤: : 非法使用非法使用 initinit/ / 必須通過必須通過 List List 類型的對象或指針來使用類型的對象或指針來使用 第10章其他2022-6-2813n使用類的非靜態(tài)成員時(shí),編譯器必須能夠識(shí)別出使用類的非靜態(tài)成員時(shí),編譯器必須能夠識(shí)別出非靜態(tài)成員屬于哪個(gè)對象。在非靜態(tài)成員屬于哪個(gè)對象。在ListItemListItem的構(gòu)造函的構(gòu)造函數(shù)中的數(shù)中的thisthis指針的類型是指針的類型是ListItemListItem* * ,而要訪問,而要訪問成員成員init()init()所需的是所需的

13、是ListList類型的對象或類型的對象或ListList* *類類型的指針。型的指針。n成員函數(shù)成員函數(shù)mf()mf()通過引用參數(shù)引用通過引用參數(shù)引用init()init(),從這里,從這里我們能夠知道成員我們能夠知道成員init()init()是針對函數(shù)實(shí)參指定的是針對函數(shù)實(shí)參指定的對象而被調(diào)用的。對象而被調(diào)用的。void List:ListItem:mfvoid List:ListItem:mf( ( const List &ilconst List &il ) ) memb = il.initmemb = il.init();(); / ok: / ok: 通過引用調(diào)

14、用通過引用調(diào)用init()init() 第10章其他2022-6-2814n嵌套類可以直接訪問外圍類的靜態(tài)成員,類型名嵌套類可以直接訪問外圍類的靜態(tài)成員,類型名,枚舉值。類型名是一個(gè),枚舉值。類型名是一個(gè)typedeftypedef名字,枚舉類名字,枚舉類型名,或是一個(gè)類名。例如:型名,或是一個(gè)類名。例如:n在在ListItemListItem的域之外,以及在外圍類的域之外,以及在外圍類List List 域之域之外引用外圍類的靜態(tài)成員類型名和枚舉名都要求外引用外圍類的靜態(tài)成員類型名和枚舉名都要求域解析操作符。域解析操作符。第10章其他2022-6-2815class List class L

15、ist public:public:typedef int (typedef int (* *pFuncpFunc)();)();enum ListStatusenum ListStatus Good, Empty, Corrupted ; Good, Empty, Corrupted ;/ ./ .private:private:class ListItemclass ListItem public:public:void check_statusvoid check_status();();ListStatusListStatus status; / ok status; / okpFun

16、cpFunc action; / ok action; / ok/ ./ .;/ ./ .;第10章其他2022-6-2816npFuncpFunc,ListStatusListStatus和和ListItemListItem都是外圍類都是外圍類List List 的作用域內(nèi)部的嵌套類型名,這三個(gè)名字以及的作用域內(nèi)部的嵌套類型名,這三個(gè)名字以及ListStatusListStatus的枚舉值都可以被用在的枚舉值都可以被用在ListItemListItem的域的域中,這些成員可以不加限定修飾地被引用。中,這些成員可以不加限定修飾地被引用。void List:ListItem:check_stat

17、usvoid List:ListItem:check_status()() ListStatusListStatus s = status; s = status;switch ( s ) switch ( s ) case case EmptyEmpty: .: .case Corrupted: .case Corrupted: .case Good: .case Good: . 第10章其他2022-6-2817n被用在嵌套類的定義中的名字(除了被用在嵌套類的定義中的名字(除了inline inline 成成員函數(shù)定義中的名字和缺省實(shí)參的名字之外)其員函數(shù)定義中的名字和缺省實(shí)參的名字之外)

18、其解析過程如下:解析過程如下:1.1.考慮出現(xiàn)在名字使用點(diǎn)之前的嵌套類的成員聲考慮出現(xiàn)在名字使用點(diǎn)之前的嵌套類的成員聲明。明。2.2.如果第如果第1 1步?jīng)]有成功則考慮出現(xiàn)在名字使用點(diǎn)步?jīng)]有成功則考慮出現(xiàn)在名字使用點(diǎn)之前的外圍類的成員聲明。之前的外圍類的成員聲明。3.3.如果第如果第2 2步?jīng)]有成功則考慮出現(xiàn)在嵌套類定義步?jīng)]有成功則考慮出現(xiàn)在嵌套類定義之前的名字空間域中的聲明。之前的名字空間域中的聲明。第10章其他2022-6-2818enum ListStatusenum ListStatus Good, Empty, Corrupted ; Good, Empty, Corrupted ;

19、class List class List public:public:/ ./ .private:private:class ListItemclass ListItem public:public:/ / 查找查找: :/ 1) / 1) 在在 List:ListItemList:ListItem 中中/ 2) / 2) 在在 List List 中中/ 3) / 3) 在全局域中在全局域中ListStatusListStatus status; / status; / 引用全局枚舉引用全局枚舉/ ./ .;/ ./ .;第10章其他2022-6-2819n編譯器首先在類編譯器首先在類Li

20、stItemListItem的域中查找的域中查找ListStatusListStatus 的聲明,因?yàn)闆]有找到成員聲明,所以編譯器接的聲明,因?yàn)闆]有找到成員聲明,所以編譯器接著在類著在類ListList的域中查找的域中查找ListStatusListStatus的聲明,因?yàn)榈穆暶?,因?yàn)樵谠贚istList類中也沒有找到聲明,于是編譯器在全局類中也沒有找到聲明,于是編譯器在全局域中查找域中查找ListStatusListStatus的聲明。在這三個(gè)域中只有的聲明。在這三個(gè)域中只有位于位于ListStatusListStatus使用點(diǎn)之前的聲明才會(huì)被編譯器使用點(diǎn)之前的聲明才會(huì)被編譯器考慮,編譯器找

21、到了全局枚舉考慮,編譯器找到了全局枚舉ListStatusListStatus的聲明的聲明,它是被用在,它是被用在statusstatus聲明中的類型。聲明中的類型。n如果在全局域中,在外圍域如果在全局域中,在外圍域ListList之外定義嵌套類之外定義嵌套類ListItemListItem,則,則ListList類的所有成員都已經(jīng)被聲明完類的所有成員都已經(jīng)被聲明完畢,因而編譯器將考慮其所有聲明,例如:畢,因而編譯器將考慮其所有聲明,例如:第10章其他2022-6-2820class List class List private:private:class ListItemclass Lis

22、tItem; ;/ ./ .public:public:enum ListStatusenum ListStatus Good, Empty, Corrupted ; Good, Empty, Corrupted ;/ ./ .;class List:ListItemclass List:ListItem public:public:/ / 查找查找: :/ 1) / 1) 在在 List:ListItemList:ListItem 中中/ 2) / 2) 在在 List List 中中/ 3) / 3) 在全局域中在全局域中ListStatus status; / List:ListStat

23、usListStatus status; / List:ListStatus/ ./ .;第10章其他2022-6-2821nListItemListItem的名字解析過程:首先在類的名字解析過程:首先在類ListItemListItem的的域中開始查找,因?yàn)闆]有找到成員聲明,所以編域中開始查找,因?yàn)闆]有找到成員聲明,所以編譯器在類譯器在類ListList的域內(nèi)查找的域內(nèi)查找ListStatusListStatus的聲明,因的聲明,因?yàn)轭悶轭怢istList的完整定義都已經(jīng)能夠看得到,所以這的完整定義都已經(jīng)能夠看得到,所以這一步查找考慮一步查找考慮ListList的所有成員,于是找到的所有成員

24、,于是找到ListList中中嵌套的嵌套的enumListStatusenumListStatus,盡管它是在,盡管它是在ListItemListItem之之后被聲明的,后被聲明的,statusstatus是是ListList的的ListStatusListStatus類型的類型的一個(gè)枚舉對象。如果一個(gè)枚舉對象。如果ListList沒有名為沒有名為ListStatusListStatus的的成員,則名字查找過程會(huì)在全局域中在嵌套類成員,則名字查找過程會(huì)在全局域中在嵌套類ListItemListItem定義之前查找聲明。定義之前查找聲明。第10章其他2022-6-2822n被用在被用在嵌套類的成

25、員函數(shù)嵌套類的成員函數(shù)定義中的名字,其解析定義中的名字,其解析過程如下:過程如下:1.1.首先考慮在成員函數(shù)局部域中的聲明。首先考慮在成員函數(shù)局部域中的聲明。2.2.如果第如果第1 1步?jīng)]有成功,則考慮所有嵌套類成員步?jīng)]有成功,則考慮所有嵌套類成員的聲明。的聲明。3.3.如果第如果第2 2步?jīng)]有成功,則考慮所有外圍類成員步?jīng)]有成功,則考慮所有外圍類成員的聲明。的聲明。4.4.如果第如果第3 3步?jīng)]有成功,則考慮在成員函數(shù)定義步?jīng)]有成功,則考慮在成員函數(shù)定義之前的名字空間域中出現(xiàn)的聲明。之前的名字空間域中出現(xiàn)的聲明。第10章其他2022-6-2823class List class List p

26、ublic:public:enum ListStatusenum ListStatus Good, Empty, Corrupted ; Good, Empty, Corrupted ;/ ./ .private:private:class ListItemclass ListItem public:public:void check_statusvoid check_status();();ListStatusListStatus status; / ok status; / ok/ ./ .;ListItemListItem * *listlist; ;/ ./ .;intint list

27、list = 0; = 0;void List:ListItem:check_statusvoid List:ListItem:check_status()() intint value = value = listlist; / ; / 哪個(gè)哪個(gè) list?list? 第10章其他2022-6-2824n很有可能程序員想讓很有可能程序員想讓check_statuscheck_status()()中的中的ListList引引用全局對象:用全局對象:nvaluevalue和全局對象和全局對象listlist的類型都是的類型都是intint,List:listList:list 成員是指針類型,在

28、沒有顯式轉(zhuǎn)換的情況它不能被成員是指針類型,在沒有顯式轉(zhuǎn)換的情況它不能被賦給賦給valuevaluen不允許不允許ListItemListItem訪問其外圍類的私有數(shù)據(jù)成員訪問其外圍類的私有數(shù)據(jù)成員listlistnlistlist是一個(gè)非靜態(tài)數(shù)據(jù)成員,在是一個(gè)非靜態(tài)數(shù)據(jù)成員,在ListItemListItem的成員函的成員函數(shù)中必須通過對象指針或引用來訪問它數(shù)中必須通過對象指針或引用來訪問它n盡管有這些原因,在成員盡管有這些原因,在成員check_statuscheck_status()()中用到中用到的名字的名字listlist仍被解析為類仍被解析為類ListList的數(shù)據(jù)成員的數(shù)據(jù)成員li

29、stlist,外圍類外圍類ListList的成員的成員listlist隱藏了全局域中的對象,隱藏了全局域中的對象,于是產(chǎn)生一個(gè)錯(cuò)誤消息,因?yàn)樵谟谑钱a(chǎn)生一個(gè)錯(cuò)誤消息,因?yàn)樵赾heck_statuscheck_status()()中使用指針中使用指針listlist是無效的。是無效的。第10章其他2022-6-2825n只有在名字解析成功之后,編譯器才會(huì)檢查訪問只有在名字解析成功之后,編譯器才會(huì)檢查訪問許可和類型兼容性。如果名字的用法本身就是錯(cuò)許可和類型兼容性。如果名字的用法本身就是錯(cuò)誤的,則名字解析過程將不會(huì)再去查找更適合于誤的,則名字解析過程將不會(huì)再去查找更適合于該名字用法的聲明,而是產(chǎn)生一個(gè)

30、錯(cuò)誤消息。該名字用法的聲明,而是產(chǎn)生一個(gè)錯(cuò)誤消息。 n為訪問全局對象為訪問全局對象listlist,需,需使用全局域操作符使用全局域操作符:void void List:ListItemList:ListItem: : check_statuscheck_status() () value = value = :list:list; / ok; / ok n如果成員函數(shù)如果成員函數(shù)check_statuscheck_status()()被定義成位于被定義成位于ListItemListItem類體中的內(nèi)聯(lián)函數(shù),則上面修改會(huì)使編類體中的內(nèi)聯(lián)函數(shù),則上面修改會(huì)使編譯器產(chǎn)生一個(gè)錯(cuò)誤消息,報(bào)告全局域中的

31、譯器產(chǎn)生一個(gè)錯(cuò)誤消息,報(bào)告全局域中的listlist沒沒有被聲明,因?yàn)榫幾g器只考慮在有被聲明,因?yàn)榫幾g器只考慮在check_statuscheck_status()()定義之前可見的全局聲明。定義之前可見的全局聲明。第10章其他2022-6-2826n類型轉(zhuǎn)換就是將一種類型的值映射為另一種類型類型轉(zhuǎn)換就是將一種類型的值映射為另一種類型的值。主要包含隱式類型轉(zhuǎn)換的值。主要包含隱式類型轉(zhuǎn)換(implicit type(implicit typeconversion)conversion)和顯式類型轉(zhuǎn)換和顯式類型轉(zhuǎn)換(explicit type (explicit type conversion)c

32、onversion)兩種。兩種。n隱式隱式- -自動(dòng)自動(dòng)n顯式顯式- -強(qiáng)制強(qiáng)制第10章其他2022-6-2827n C+C+定義了一組內(nèi)置類型對象之間的標(biāo)準(zhǔn)轉(zhuǎn)換,在必要定義了一組內(nèi)置類型對象之間的標(biāo)準(zhǔn)轉(zhuǎn)換,在必要時(shí)它們被編譯器隱式地應(yīng)用到對象上,隱式類型轉(zhuǎn)換發(fā)時(shí)它們被編譯器隱式地應(yīng)用到對象上,隱式類型轉(zhuǎn)換發(fā)生在下列這些典型的情況下:生在下列這些典型的情況下:1.1.在混合類型的算術(shù)表達(dá)式中。在這種情況下,在混合類型的算術(shù)表達(dá)式中。在這種情況下,最寬的數(shù)最寬的數(shù)據(jù)類型成為目標(biāo)轉(zhuǎn)換類型。據(jù)類型成為目標(biāo)轉(zhuǎn)換類型。這也被稱為算術(shù)轉(zhuǎn)換這也被稱為算術(shù)轉(zhuǎn)換(arithmetic conversion)(a

33、rithmetic conversion)。例如:。例如:3.14159+33.14159+32.2.用一種類型的表達(dá)式賦值給另一種類型的對象。在這種用一種類型的表達(dá)式賦值給另一種類型的對象。在這種情況下,目標(biāo)轉(zhuǎn)換類型是被賦值對象的類型。例如:情況下,目標(biāo)轉(zhuǎn)換類型是被賦值對象的類型。例如:int int * *pi = 0; int ivalpi = 0; int ival = 3.14159; = 3.14159;第10章其他2022-6-28283.3.把一個(gè)表達(dá)式傳遞給一個(gè)函數(shù)調(diào)用把一個(gè)表達(dá)式傳遞給一個(gè)函數(shù)調(diào)用,表達(dá)式的類型與形表達(dá)式的類型與形式參數(shù)的類型不相同。在這種情況下,目標(biāo)轉(zhuǎn)換類

34、型是式參數(shù)的類型不相同。在這種情況下,目標(biāo)轉(zhuǎn)換類型是形式參數(shù)的類型。形式參數(shù)的類型。例如:例如:intint a=2; sqrt(2) a=2; sqrt(2) 2-2.02-2.04.4.從一個(gè)函數(shù)返回一個(gè)表達(dá)式,表達(dá)式的類型與返回類型從一個(gè)函數(shù)返回一個(gè)表達(dá)式,表達(dá)式的類型與返回類型不相同。在這種情況下,目標(biāo)轉(zhuǎn)換類型是函數(shù)的返回類不相同。在這種情況下,目標(biāo)轉(zhuǎn)換類型是函數(shù)的返回類型。例如:型。例如:double difference( double difference( intint ival1, ival1, intint ival2 ) ival2 ) / / 返回值被提升為返回值被提升

35、為doubledouble 類型類型return ival1 - ival2;return ival1 - ival2; 第10章其他2022-6-2829n 顯式顯式類型轉(zhuǎn)換也被稱為強(qiáng)制類型轉(zhuǎn)換類型轉(zhuǎn)換也被稱為強(qiáng)制類型轉(zhuǎn)換(cast(cast) ),包括下列包括下列強(qiáng)制類型轉(zhuǎn)換操作符強(qiáng)制類型轉(zhuǎn)換操作符:static_caststatic_cast,dynamic_castdynamic_cast,const_castconst_cast,reinterpret_castreinterpret_cast,()()等。等。第10章其他2022-6-2830n 顯式類型轉(zhuǎn)換發(fā)生在下列這些典型的情況

36、下:顯式類型轉(zhuǎn)換發(fā)生在下列這些典型的情況下:1.1.把把voidvoid* *型的指針賦值給任意顯式類型時(shí),型的指針賦值給任意顯式類型時(shí),C+C+要求顯式要求顯式強(qiáng)制轉(zhuǎn)換。例如:強(qiáng)制轉(zhuǎn)換。例如:intint * *pi = 0;pi = 0;void void * * pv pv = pi; = pi;char char * * pc = pc = static_caststatic_cast char ( pv( pv ); );2.2.希望改變通常的標(biāo)準(zhǔn)轉(zhuǎn)換。例如:希望改變通常的標(biāo)準(zhǔn)轉(zhuǎn)換。例如:double dval; int ivaldouble dval; int ival; ; iv

37、al += dvalival += dval; ;ival += static_cast( dvalival += static_cast( dval ); );3.3.避免出現(xiàn)多種轉(zhuǎn)換可能的歧義情況。避免出現(xiàn)多種轉(zhuǎn)換可能的歧義情況。第10章其他2022-6-2831n dynamic_castdynamic_cast一般一般被用來執(zhí)行從基類指針到派生類指針被用來執(zhí)行從基類指針到派生類指針的安全轉(zhuǎn)換,常常被稱為安全的向下轉(zhuǎn)換。的安全轉(zhuǎn)換,常常被稱為安全的向下轉(zhuǎn)換。是在運(yùn)行時(shí)是在運(yùn)行時(shí)刻執(zhí)行的。失敗返回刻執(zhí)行的。失敗返回0 0。manager manager * *pm = dynamic_ca

38、st managerpm = dynamic_cast( pe ( pe ); );n const_castconst_cast將轉(zhuǎn)換掉表達(dá)式的常量性,例如:將轉(zhuǎn)換掉表達(dá)式的常量性,例如:extern char extern char * *string_copystring_copy( char( char* * ); );const char const char * *pc_strpc_str; ;char char * *pc = string_copypc = string_copy( ( const_castconst_cast char ( pc_str( pc_str ); )

39、;n reinterpre_castreinterpre_cast通常對于操作數(shù)的位模式執(zhí)行一個(gè)比通常對于操作數(shù)的位模式執(zhí)行一個(gè)比較低層次的重新解釋,例如:較低層次的重新解釋,例如:complex complex * *pcom;pcom;char char * *pc = reinterpret_cast charpc = reinterpret_cast( pcom ); ( pcom );第10章其他2022-6-2832n 舊式強(qiáng)制類型轉(zhuǎn)換舊式強(qiáng)制類型轉(zhuǎn)換char char * *pc = pc = (char(char* *) ) pcom pcom; ;/C/C風(fēng)格風(fēng)格int iv

40、alint ival = = (int(int) ) 3.14159; 3.14159;/C/C風(fēng)格風(fēng)格int addr_valueint addr_value = = intint( &ival( &ival ); );/C+/C+風(fēng)格風(fēng)格第10章其他2022-6-2833n C+C+提供了一種機(jī)制,通過它,每個(gè)類都可以定義一組提供了一種機(jī)制,通過它,每個(gè)類都可以定義一組可被應(yīng)用在該類型對象上的轉(zhuǎn)換??杀粦?yīng)用在該類型對象上的轉(zhuǎn)換。n 轉(zhuǎn)換函數(shù)轉(zhuǎn)換函數(shù)(conversion function)(conversion function)是一種特殊類型的類是一種特殊類型的類成員函數(shù)

41、,它定義了一個(gè)由用戶定義的轉(zhuǎn)換,以便把一成員函數(shù),它定義了一個(gè)由用戶定義的轉(zhuǎn)換,以便把一個(gè)類對象轉(zhuǎn)換成某種其他的類型。在類體中通過指定關(guān)個(gè)類對象轉(zhuǎn)換成某種其他的類型。在類體中通過指定關(guān)鍵字鍵字operatoroperator,并在其后加上轉(zhuǎn)換的目標(biāo)類型后我們就,并在其后加上轉(zhuǎn)換的目標(biāo)類型后我們就可以聲明轉(zhuǎn)換函數(shù)??梢月暶鬓D(zhuǎn)換函數(shù)。n 轉(zhuǎn)換函數(shù)又稱類型強(qiáng)制轉(zhuǎn)換成員函數(shù),它是類中的一個(gè)轉(zhuǎn)換函數(shù)又稱類型強(qiáng)制轉(zhuǎn)換成員函數(shù),它是類中的一個(gè)非靜態(tài)成員函數(shù)。它的定義格式如下:非靜態(tài)成員函數(shù)。它的定義格式如下:第10章其他2022-6-2834class class 1 public:public:opera

42、tor operator ();2(); n 這個(gè)轉(zhuǎn)換函數(shù)定義了由這個(gè)轉(zhuǎn)換函數(shù)定義了由 1到到 2之間的映射關(guān)系。之間的映射關(guān)系。 2可以是可以是內(nèi)置類型、類內(nèi)置類型、類類型或類型或typedeftypedef。下面通過一個(gè)例子說明轉(zhuǎn)換函數(shù)的功。下面通過一個(gè)例子說明轉(zhuǎn)換函數(shù)的功能。能。第10章其他2022-6-2835class Rationalclass Rationalpublic:public:Rational(int d, intRational(int d, int n) n)den = d;den = d;num = n;num = n; operator double(); /o

43、perator double(); /類型轉(zhuǎn)換函數(shù)類型轉(zhuǎn)換函數(shù)private:private:intint den, num; den, num;Rational:operatorRational:operator double() double()return double(den)/double(numreturn double(den)/double(num);); intint main() main() Rational r(5, 8);Rational r(5, 8);double d = 4.7;double d = 4.7;d+=r;d+=r;coutdendlcoutdend

44、l; ;return 0;return 0; 第10章其他2022-6-2836n 程序輸出結(jié)果:程序輸出結(jié)果:5.3255.325n 由程序可知,由程序可知,d d是一個(gè)是一個(gè)doubledouble型數(shù)值,型數(shù)值,r r是是RationalRational類的類的對象,這兩個(gè)不同類型的數(shù)據(jù)進(jìn)行加法之所以能夠進(jìn)行對象,這兩個(gè)不同類型的數(shù)據(jù)進(jìn)行加法之所以能夠進(jìn)行是得益于轉(zhuǎn)換函數(shù)是得益于轉(zhuǎn)換函數(shù) operator double()operator double()。為使上述加法。為使上述加法能夠進(jìn)行,編譯系統(tǒng)先檢查類能夠進(jìn)行,編譯系統(tǒng)先檢查類RationalRational的說明,看是否的說明,

45、看是否存在在下轉(zhuǎn)換函數(shù)能夠?qū)⒋嬖谠谙罗D(zhuǎn)換函數(shù)能夠?qū)ationalRational類型的操作數(shù)轉(zhuǎn)換為類型的操作數(shù)轉(zhuǎn)換為 doubledouble類型的操作數(shù)。由于類型的操作數(shù)。由于RationalRational類中說明了轉(zhuǎn)換函類中說明了轉(zhuǎn)換函數(shù)數(shù)operator double()operator double(),它可以在程序運(yùn)行時(shí)進(jìn)行上述,它可以在程序運(yùn)行時(shí)進(jìn)行上述類型轉(zhuǎn)換,因此,該程序中實(shí)現(xiàn)了類型轉(zhuǎn)換,因此,該程序中實(shí)現(xiàn)了d+=r;d+=r;的操作。的操作。第10章其他2022-6-2837n 定義轉(zhuǎn)換函數(shù)時(shí)應(yīng)注意如下幾點(diǎn):定義轉(zhuǎn)換函數(shù)時(shí)應(yīng)注意如下幾點(diǎn):1.1.轉(zhuǎn)換函數(shù)是用戶定義的成員函

46、數(shù),但它要是非靜態(tài)的。轉(zhuǎn)換函數(shù)是用戶定義的成員函數(shù),但它要是非靜態(tài)的。2.2.轉(zhuǎn)換函數(shù)的名稱是類型轉(zhuǎn)換的目標(biāo)類型,因此,不必再轉(zhuǎn)換函數(shù)的名稱是類型轉(zhuǎn)換的目標(biāo)類型,因此,不必再為它指定返回值類型。為它指定返回值類型。3.3.轉(zhuǎn)換函數(shù)是被用于本類型的數(shù)值或變量轉(zhuǎn)換為其他的類轉(zhuǎn)換函數(shù)是被用于本類型的數(shù)值或變量轉(zhuǎn)換為其他的類型,也不必帶參數(shù)。型,也不必帶參數(shù)。4.4.轉(zhuǎn)換函數(shù)函數(shù)還不能定義為友元函數(shù)。轉(zhuǎn)換函數(shù)函數(shù)還不能定義為友元函數(shù)。5.5.不能定義到不能定義到voidvoid的轉(zhuǎn)換,也不允許轉(zhuǎn)換成數(shù)組或者函數(shù)的轉(zhuǎn)換,也不允許轉(zhuǎn)換成數(shù)組或者函數(shù)類型。類型。6.6.轉(zhuǎn)換常定義為轉(zhuǎn)換常定義為constco

47、nst形式,原因是它并不改變數(shù)據(jù)成員形式,原因是它并不改變數(shù)據(jù)成員的值。的值。第10章其他2022-6-2838n 轉(zhuǎn)換操作符過于強(qiáng)大,它可以定義到一種內(nèi)置類型的轉(zhuǎn)轉(zhuǎn)換操作符過于強(qiáng)大,它可以定義到一種內(nèi)置類型的轉(zhuǎn)換,然而這種內(nèi)置類型本身是可能繼續(xù)轉(zhuǎn)換成其他的內(nèi)換,然而這種內(nèi)置類型本身是可能繼續(xù)轉(zhuǎn)換成其他的內(nèi)置類型的,如置類型的,如operator intoperator int() const() const定義了到定義了到intint型的型的轉(zhuǎn)換,然后轉(zhuǎn)換,然后intint型可以轉(zhuǎn)換到型可以轉(zhuǎn)換到floatfloat、doubledouble、ongong等類等類型,這樣極不容易確定編譯器為

48、我們做了什么,在出現(xiàn)型,這樣極不容易確定編譯器為我們做了什么,在出現(xiàn)問題后,也極不容易定位錯(cuò)誤。問題后,也極不容易定位錯(cuò)誤。n 當(dāng)類類型定義了一個(gè)到基本類型當(dāng)類類型定義了一個(gè)到基本類型A A的轉(zhuǎn)換后,可能在實(shí)的轉(zhuǎn)換后,可能在實(shí)際中轉(zhuǎn)換到另一基本類型際中轉(zhuǎn)換到另一基本類型B B,如果再定義一個(gè)到基本類,如果再定義一個(gè)到基本類型型C C的轉(zhuǎn)換,而的轉(zhuǎn)換,而C C也可以轉(zhuǎn)換到也可以轉(zhuǎn)換到B B。這時(shí)就會(huì)在產(chǎn)生二義。這時(shí)就會(huì)在產(chǎn)生二義性,如性,如A A為為intint,B B為為long doublelong double,C C為為doubledouble,在產(chǎn)生,在產(chǎn)生自定義類型的對象時(shí),需要轉(zhuǎn)換

49、,就會(huì)使得編譯器并不自定義類型的對象時(shí),需要轉(zhuǎn)換,就會(huì)使得編譯器并不知道如何處理,到底是調(diào)用哪個(gè)轉(zhuǎn)換。知道如何處理,到底是調(diào)用哪個(gè)轉(zhuǎn)換。第10章其他2022-6-2839n 使用自定義轉(zhuǎn)換時(shí),定義轉(zhuǎn)換多,會(huì)像上述那樣引發(fā)二使用自定義轉(zhuǎn)換時(shí),定義轉(zhuǎn)換多,會(huì)像上述那樣引發(fā)二義性。避免的方法是,最好在定義到內(nèi)置類型的轉(zhuǎn)換時(shí)義性。避免的方法是,最好在定義到內(nèi)置類型的轉(zhuǎn)換時(shí),只定義一個(gè),因?yàn)閮?nèi)置類型之間的轉(zhuǎn)換太靈活了。,只定義一個(gè),因?yàn)閮?nèi)置類型之間的轉(zhuǎn)換太靈活了。n 另外,構(gòu)造函數(shù)和轉(zhuǎn)換函數(shù)之間也可能存在二義性。后另外,構(gòu)造函數(shù)和轉(zhuǎn)換函數(shù)之間也可能存在二義性。后面會(huì)講到。面會(huì)講到。第10章其他2022-6-2840n 在一個(gè)類的構(gòu)造函數(shù)中,凡是只帶一個(gè)參數(shù)的構(gòu)造函數(shù)在一個(gè)類的構(gòu)造函數(shù)中,凡是只帶一個(gè)參數(shù)的構(gòu)造函數(shù),都定義了一組隱式轉(zhuǎn)換,把構(gòu)造函數(shù)的參數(shù)類型轉(zhuǎn)換,都定義了一組隱式轉(zhuǎn)換,把構(gòu)造函數(shù)的參數(shù)類型轉(zhuǎn)換為該類的類型。為該類的類型。n 如果需要,編譯器會(huì)在調(diào)用構(gòu)造函數(shù)執(zhí)行用戶定義的轉(zhuǎn)如果需要,編譯器會(huì)在調(diào)用構(gòu)造函數(shù)執(zhí)行用戶定義的轉(zhuǎn)換之前,在實(shí)參上應(yīng)用標(biāo)準(zhǔn)轉(zhuǎn)換序列。換之前,在實(shí)參上應(yīng)用標(biāo)準(zhǔn)轉(zhuǎn)換序列。n 下面通過一個(gè)例子進(jìn)一步說明單參數(shù)構(gòu)造函數(shù)的類型轉(zhuǎn)下面通過一個(gè)例子進(jìn)一步說明單參數(shù)構(gòu)造函數(shù)的類型轉(zhuǎn)換功能。換功能。第10章其他2022-6-

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論