五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

Godot Source Code Note 3

2023-06-27 15:31 作者:中專人  | 我要投稿

非靜態(tài)成員函數(shù)指針類型擦除

在Godot源碼中,Object類中聲明并定義了一個(gè)名為_bind_methods的函數(shù):

該函數(shù)通過調(diào)用ClassDB類中的靜態(tài)方法bind_method()完成Object類中成員函數(shù)的注冊。

由于Godot中關(guān)于Scene的類均直接或間接繼承自O(shè)bject類,因此類似Node3D、Area3D的類就可以覆寫(注意:不是虛函數(shù)的重寫)父類中bind_method()方法完成自身類中成員函數(shù)的注冊。

class_db.h文件中對(duì)ClassDB::bind_method()函數(shù)的定義:

args數(shù)組存儲(chǔ)函數(shù)的默認(rèn)實(shí)參,argptrs數(shù)組則存儲(chǔ)args數(shù)組中對(duì)應(yīng)函數(shù)默認(rèn)實(shí)參的地址。接下來通過create_method_bind函數(shù),將成員函數(shù)指針包裝成一個(gè)MethodBind派生類對(duì)象,并返回MethodBind基類指針。

create_method_bind函數(shù)的四個(gè)重載版本定義在method_bind.h文件中:

在此以第一種重載版本為例,其余不再贅述,其實(shí)現(xiàn)如下:

這里主要討論無TYPED_METHOD_BIND宏的MethodBindT類構(gòu)造方法(MethodBindT類繼承自MethodBind類),這是簡化了的MethodBindT類定義:

可以看出MethodBindT類有一個(gè)void (MB_T::*)(P...)類型的成員變量method,而其構(gòu)造函數(shù)接受一個(gè)相同類型的變量p_method并將其賦值給method。

從create_method_bind函數(shù)中也可以看到,在MethodBindT構(gòu)造函數(shù)中,reinterpret_cast<void (MB_T::*)(P...)>(p_method)將p_method重新解釋為void (MB_T::*)(P...)類型的成員函數(shù)指針。

在代碼中找到了關(guān)于MB_T的部分:

也就是說,MB_T只是__UnexistingClass的別名,但__UnexistingClass只有聲明沒有定義!

為什么要這么做?

為了弄清這個(gè)問題,不得不簡要了解一下C++類中的內(nèi)存布局。

概念上來說,從C++類中實(shí)例化出的每個(gè)對(duì)象,都獨(dú)立擁有非靜態(tài)的成員變量數(shù)據(jù)與成員函數(shù)代碼。

單獨(dú)為每個(gè)對(duì)象保存成員函數(shù)代碼段會(huì)造成大量內(nèi)存浪費(fèi),因此成員函數(shù)代碼段其實(shí)是僅有一份且共享地址的。

不難猜測,&ClassName::FunctionName取得的結(jié)構(gòu)體一定包含成員函數(shù)地址(注意:為什么是結(jié)構(gòu)體,而不僅僅是函數(shù)地址,后面會(huì)提到)。

眾所周知,非靜態(tài)成員函數(shù)的調(diào)用必須要在對(duì)象中,那么僅僅知道成員函數(shù)地址還不行,因此編譯器會(huì)在調(diào)用成員函數(shù)時(shí)傳入this指針以代表當(dāng)前對(duì)象。這樣,就可以完成對(duì)象對(duì)成員函數(shù)的調(diào)用。

這個(gè)所謂的成員函數(shù)指針到底是什么?

首先根據(jù)之前的推測,成員函數(shù)指針中一定包含了對(duì)應(yīng)函數(shù)代碼段地址。

那么為什么成員函數(shù)指針無法轉(zhuǎn)換為一個(gè)函數(shù)地址呢?

考慮一下多繼承的情況,比如D類同時(shí)繼承了A類和B類,那么在調(diào)用父類(A類和B類)成員函數(shù)時(shí),需要根據(jù)父類(A類和B類)在子類(D類)中的內(nèi)存布局來調(diào)整this指針并傳入對(duì)應(yīng)父類(A類和B類)成員函數(shù)中。

那么很容易想到,成員函數(shù)指針包含的另一個(gè)數(shù)據(jù)肯定與類中內(nèi)存布局有關(guān),即父類在子類中的偏移量,而這就可滿足計(jì)算得到父類this指針的要求。

總結(jié)一下,成員函數(shù)指針應(yīng)該是一個(gè)結(jié)構(gòu)體,其中包含了成員函數(shù)代碼段地址與類的內(nèi)存偏移量。

&ClassName::FunctionName是對(duì)象無關(guān)的,因此不經(jīng)過對(duì)象也能直接取到成員函數(shù)指針也就不奇怪了。

當(dāng)然了,以上僅為一種可能的實(shí)現(xiàn)方式,具體實(shí)現(xiàn)根據(jù)平臺(tái)不同存在差異。

解釋清楚成員函數(shù)指針,reinterpret_cast<void (MB_T::*)(P...)>(p_method)也就很好理解了。

任意類型的成員函數(shù)指針p_method,可以直接解釋為結(jié)構(gòu)相同的__UnexistingClass::*類型,并賦值給method變量。

由此便完成了對(duì)成員函數(shù)指針的類型擦除。

從MethodBindT的構(gòu)造函數(shù)中返回,就得到了成員函數(shù)指針的MethodBind包裝類型的指針。

接下來將類的名稱存儲(chǔ)在MethodBind對(duì)象的成員變量中,將指針從create_method_bind中返回。

標(biāo)記返回值類型是否為Object指針后,調(diào)用bind_methodfi()函數(shù)完成非靜態(tài)成員函數(shù)注冊。

最后再看一下成員函數(shù)指針的調(diào)用方法:

傳入具體對(duì)象完成成員函數(shù)的調(diào)用,語法為:

最后再附一個(gè)簡化后的例子:

但在C++11后可以使用std::function庫函數(shù)完成對(duì)函數(shù)的包裝:


如侵刪。
歡迎評(píng)論指正。

Godot Source Code Note 3的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
碌曲县| 子洲县| 汉阴县| 京山县| 康马县| 溆浦县| 桐乡市| 呼图壁县| 潞城市| 万安县| 崇州市| 大悟县| 喀什市| 江北区| 焦作市| 永吉县| 舟曲县| 年辖:市辖区| 云龙县| 东方市| 塔河县| 高淳县| 长海县| 海口市| 府谷县| 苏尼特右旗| 桂阳县| 陵水| 资溪县| 鸡西市| 大名县| 滕州市| 延吉市| 漯河市| 四会市| 长阳| 曲松县| 依兰县| 辽宁省| 胶州市| 高尔夫|