如何動態儲存不同類的對象的成員函數的地址?–解決

來源:互聯網
上載者:User

問題的提出:

就是想要實現一個容器類,可以儲存不同類型的函數地址,包括成員函數,且
是屬於不同類的對象的,即類不同,對象不同,函數不同(參數與傳回值相同);
如題不知把傳進來的不同類的函數地址儲存下來,注意:這個儲存下來的地址的生命期要
和對象的生命期相同;

研究過程:

1 研究了一個晚上,發現不同函數的資訊是可以儲存下來的(即把函數地址當作char數組可
以儲存下來,用memcpy函數可以,),但是在調用時需要去用函數的類型(即類)來規定
(或解釋)這個儲存的函數地址,但是類型又不知道,所以現在是可以儲存卻讀(用)不
出來,關鍵就是類型不能被儲存下來,不能再使用。不知有什麼辦法可以把類型儲存下來

(唉,感覺C++的指標太不靈活了)。

2 今天研究了一天,發現解決這個問題的辦法就是“委託”(Delegates),下面的文章講的

很詳細:
原文:Member Function Pointers and the Fastest Possible C++ Delegates
http://www.codeproject.com/cpp/FastDelegate.asp
中文翻譯:成員函數指標與高效能的C++委託
http://blog.csdn.net/hifrog/archive/2004/07/03/33068.aspx
原始碼:http://bbs.nju.edu.cn/file/Y/yangjiudan/delegate.rar

作者寫了一個類用於解決C++委託問題。
我大概是這樣理解的,
對於普通函數和靜態成員函數應該沒問題,按常規的方法就可以;
而對於非靜態成員函數,其調用需要知道對象的地址T *O,對象的類型T,成員函數的
地址ReturnType (T::*menfunc)(InputType);
對象的類型可以通過函數模板得到T,則對象的地址O,成員函數的地址memfunc也就知道了

則可以通過(O->*menfunc)(InputType para);來調用此函數;
到此就可以實現調用不同類型的對象的成員函數的目的。
但是此時調用函數是即時性的,即你只能在得到函數資訊的函數中去調用函數,出了此函
數,這些被調用的函數的資訊就沒有了,所以你不能做到用一個函數把需要被調用的函數
添加進去,再在另一個函數中去正式去調用這些添加的函數。所以此時還不能達到目的。

所以關鍵的問題是能把每次傳入的不同類型的對象及其成員函數儲存下來,也就是需要一
個對應類型的變數去儲存,但是類型又不知,也不同,而通過類模板也只能知道有限種類
的類型(其實這樣也行,讓使用者把要用到的類型通過模板參數傳入,但類型的數目是有
最大值的,然後在類內部為每一種傳入型別宣告一個變數用來儲存添加的被調用函數的信
息,在添加函數中利用RTTI去把相應的資訊存入相應的變數,在調用時利用變數的資訊就
可以成功地調用該函數了,但是這樣實現的方法很笨(自己想的,沒辦法)很不靈活),
所以只能另求他發,這就是該文作者的方法:大概是這樣的,關鍵還在於對象資訊儲存,
雖然不同類型的對象的資訊不同,但對於同一編譯器不同類型的對象的地址和成員函數地
址的結構(構成)是相同的(只是不同類型其內容會不同而已),所以可以定義一個一般
類型(地址結構要最大),這樣把其他的類型的地址資訊就可以強制轉換(reinter_cast
,沒記錯吧)並且不會丟失任何資訊,這一步是通過union來實現的,這樣需要的資訊就保
存下來了,下面就需要讀(用)出來,前面說了成員函數的調用也是需要具體類型資訊的
,但現在還是沒有把原類型儲存下來(這是做不到的),只有轉換後的類型資訊,那該怎麼
辦呢,有東西用不了,那不就根沒有一樣?不對,那是因為你不會用,怎麼用?像編譯器
一樣用,編譯器是根據類型去通過對象的地址和成員函數地址的結構去最終得到真正的地
址(具體看原文),所以我們只要像編譯器一樣,在知道類型的時候(也就是添加函數時)
自己把真正的地址儲存下來。
然後在調用時,讀出真正的地址通過(*對象地址->*成員函數真正地址)(輸入參數)調用相
應的函數,其實就是本該編譯器做的事情,去自己作,所以可以做編譯器做不了的事;還
有一點,作者實現的對函數的調用是通過函數對象來實現的(即重載()運算子),所以你
得到的函數的運行結果,而不是函數。
哎呀,真亂,不知自己的理解對不對,希望有興趣的好好看看作者的原文和源碼,
大家好好交流一下。
源碼中有個demo大家可以看一下效果

問題的總結:

就是C++中的委託的實現,用boost中的function類可以(沒驗證),

用上面提到的Fastde Delegate也可以實現(效率高),另外CodeProject中有一類文章講委託 (Delegates)的;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.