日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

friend keyword 对于模板 并不只不过友元!!!

發(fā)布時(shí)間:2025/4/14 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 friend keyword 对于模板 并不只不过友元!!! 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

friend是C++中封裝的漏網(wǎng)之魚。

C++中的friend同意其它的類或者是函數(shù)訪問本類的不論什么成員。甚至是private成員,僅僅要該類聲明其為友元。

但是,在有些情況下,并非同意外界訪問類的內(nèi)部實(shí)現(xiàn)而使用友元

這就是在 “模板定義” 與 “隱式類型轉(zhuǎn)換” 之間的一個(gè)trick了。

首先,看一個(gè)簡單的有理數(shù)的模板類。該類定義了有理數(shù),而且實(shí)現(xiàn)有理數(shù)的乘法。


注:下述代碼中,將operator*聲明為非成員函數(shù)。是由于?

“假設(shè)你須要對(duì)成員函數(shù)全部的參數(shù)(全部的,當(dāng)然也就包含this指針啦)進(jìn)行類型轉(zhuǎn)換。那么將該函數(shù)聲明為非成員函數(shù)”。

也就是說,僅僅有當(dāng)參數(shù)位于參數(shù)列的時(shí)候,這個(gè)參數(shù)才是隱式類型裝換的合格參與者。


updated:這里的參數(shù)列指的就是函數(shù)的形參列表!!!

可是類的成員函數(shù)的那個(gè)隱式參數(shù)(即this指針)不是隱式轉(zhuǎn)換的合格參與者!。


這對(duì)C++模板類相同適用。



在上述代碼中。重載了 * 符號(hào)。用于計(jì)算兩個(gè)有理數(shù)之間的乘法。


一個(gè)自然而然的道理,假設(shè)我們須要支持 有理數(shù) * 自然數(shù) ,這是一個(gè)無可厚非的要求。當(dāng)我們才有以下的調(diào)用?


Rational<int> a = Rational(1,2);

Rational<int> ret = a * 2;?


在非模板類中。該函數(shù)會(huì)將2進(jìn)行隱式類型轉(zhuǎn)換為Rational對(duì)象。再進(jìn)行乘積運(yùn)算。


糟糕!編譯不通過。在非模板類中這是非常正常的事,但是在模板類中卻出現(xiàn)了問題.


簡言之。編譯器陷入了“糾結(jié)”的境界!!

。。


以下一一進(jìn)行分析:

當(dāng)編譯器看到operator*的調(diào)用的時(shí)候。編譯器不知道我們想要調(diào)用什么函數(shù),由于編譯器看到這個(gè)模板函數(shù)時(shí)。第一要做的就是將函數(shù)實(shí)例化出來,也就是要首先判斷出T的類型可是幾經(jīng)周折。發(fā)現(xiàn)不行。


首先。為了推導(dǎo)出T, 編譯器對(duì) * 調(diào)用的兩個(gè)參數(shù)進(jìn)行入手,分別為 Rational<int> ? 和 int, 由第一個(gè)參數(shù)能夠非常easy的知道得到 T?為int。 可是在第二個(gè)實(shí)參呢,編譯器怎么判斷 T 的類型???你或許會(huì)說,此時(shí)編譯器就應(yīng)該使用 Rational<int> 的隱式構(gòu)造函數(shù)?啊。

不就能夠 推導(dǎo)出 T 的類型了嗎。?

可是。編譯器絕不會(huì)這么做,由于在 模板實(shí)參 的推導(dǎo)過程其中是不會(huì) 考慮隱式轉(zhuǎn)換的


這是本文最重要的一句話。


因此,在面對(duì)這種實(shí)參推導(dǎo) 的問題是,friend 便出場了,因?yàn)?friend 能夠在 ?模板類 中指明某個(gè)特定的函數(shù)。也就是說。在函數(shù)調(diào)用之前。聲明該函數(shù)。那么在函數(shù)調(diào)用時(shí),對(duì)應(yīng)的類模板 就不再須要 依賴于 模板實(shí)參的推導(dǎo)了,而僅僅須要對(duì)這個(gè)友元函數(shù)進(jìn)行參數(shù)推導(dǎo)就可以。


因此將operator * 聲明為該類的友元之后。編譯器的行為便不一樣了

類模板并不依賴于實(shí)參的推導(dǎo)(此時(shí)operator*函數(shù)僅僅是該類的一個(gè)模板友元函數(shù))。由于此時(shí)的實(shí)參推導(dǎo)僅僅施行于該友元模板函數(shù)身上,所以編譯器總是可以在Rational類實(shí)例化的時(shí)候得知T。


最最核心的一段話:

在onehalf 對(duì)象被定義的時(shí)候,Rational函數(shù)就被實(shí)例化了,對(duì)應(yīng)的,它的友元函數(shù) ?operator* 也就被實(shí)例化出來了,也就是說,此時(shí)的operator *?不再是一個(gè)模板函數(shù)了,那么 onehalf ?* ?2 的時(shí)候,便是調(diào)用這個(gè)已經(jīng)被實(shí)例化的函數(shù)了。于是乎。隱式類型轉(zhuǎn)換便能夠使用與參數(shù)推導(dǎo)了。


可是。另一個(gè)問題,便是鏈接時(shí)的問題了,此時(shí),編譯器知道我們要調(diào)用的是哪個(gè)函數(shù)了,可是如今那個(gè)函數(shù)僅僅是被聲明在Rational類中,并沒有實(shí)現(xiàn)它。 假設(shè)我們?cè)赗ational外部定義該函數(shù),這是行不通的。


因此,僅僅在類定義體中聲明該函數(shù),假設(shè)不定義的話,連接器便會(huì)發(fā)出抱怨,找不到定義體。

(updated:這里該函數(shù)的定義必須由類定義負(fù)責(zé),否則該函數(shù)就必須是如今類的外面,那么自然而然該函數(shù)就必須得是模板函數(shù),那么參數(shù)推導(dǎo)又不起作用了。!!

因此必須定義在函數(shù)的內(nèi)部。!!)

因此,將 operator* 聲明為友元函數(shù)而且將實(shí)現(xiàn)定義在類中。


于是,正確的Rational模板類的定義為:


?

執(zhí)行結(jié)果為:



大功告成!!

上述代碼成功的實(shí)現(xiàn)了我們的功能!。!


于是,在類模板定義時(shí)。出現(xiàn)了相同的話,假設(shè) ?在編寫一個(gè)類模板的時(shí)候,而 該類的與模板相關(guān)的函數(shù) ?須要支持函數(shù)參數(shù)

隱式轉(zhuǎn)換的時(shí)候,將該函數(shù)定義為模板類類中的friend函數(shù)。


updated:模板函數(shù)對(duì)于參數(shù)的類型推導(dǎo)是絕對(duì)不會(huì)考慮 “構(gòu)造函數(shù)的隱式類型轉(zhuǎn)換的”!

這與一般的函數(shù)調(diào)用是不一樣的。因此我們假設(shè)須要對(duì)函數(shù)的參數(shù)進(jìn)行類型推導(dǎo),那么就須要將該函數(shù)定義為非模板類型,這是編譯器就會(huì)陷入兩難的境界:

然而。對(duì)于一般的函數(shù)(非模板函數(shù))。編譯器是會(huì)進(jìn)行參數(shù)推導(dǎo)的(包含調(diào)用non-explicit構(gòu)造函數(shù))!

。!

??1在參數(shù)推導(dǎo)時(shí)使用隱式轉(zhuǎn)換??2?為了讓這個(gè)函數(shù)被具現(xiàn)化,我們又須要將它聲明在模板類的內(nèi)部!

??

?friend

!!!將函數(shù)的聲明與定義均置于類內(nèi)部。



轉(zhuǎn)載于:https://www.cnblogs.com/mengfanrong/p/5140519.html

總結(jié)

以上是生活随笔為你收集整理的friend keyword 对于模板 并不只不过友元!!!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。