国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

C++標準編程:虛函數與內聯

發布時間:2011-5-1 20:09    發布者:1046235000
關鍵詞: 內聯 , 虛函數
曾經在討論C++的時候,經常會問到:“虛函數能被聲明為內聯嗎?”現在,我們幾乎聽不到這個問題了。現在聽到的是:“你不應該使print成為內聯的。聲明一個虛函數為內聯是錯誤的!”
    這種說法的兩個主要的原因是(1)虛函數是在運行期決議而內聯是一個編譯期動作,所以,我們將虛函數聲明為內聯并得不到什么效果;(2)聲明一個虛函數為內聯導致了函數的多分拷貝,而且我們為一個不應該在任何時候內聯的函數白白花費了存儲空間。這樣做很沒腦子。
    不過,事實并不是這樣。我們先來看看第一個:許多情況下,虛擬函數都被靜態地決議了——比如在派生類虛擬函數中調用基類的虛擬函數的時候。為什么這樣做呢?封裝。一個比較明顯的例子就是派生類析構函數調用鏈。所有的虛析構函數,除了最初觸發這個析構鏈的虛析構函數,都被靜態的決議了。如果不將基類的虛析構函數內聯,我們無法從中獲利[a]。這和不內聯一個虛擬析構函數有什么不同嗎?如果繼承體系層次比較深并且有許多這樣的類的實例要被銷毀的話,答案是肯定的。
    再來看另外一個不用析構函數的例子,想象一下設計一個圖書館類。我們將MaterialLocation作為抽象類LibraryMaterial的一個成員。將它的print成員函數聲明為一個純虛函數,并且提供函數定義:它輸出MaterialLocation。
    class LibraryMaterial {
    private:
    MaterialLocation _loc; // shared data
    // ...
    public:
    // declares pure virtual function
    inline virtual void print( ostream& = cout ) = 0;
    };
    // we actually want to encapsulate the handling of the
    // location of the material within a base class
    // LibraryMaterial print() method - we just don’t want it
    // invoked through the virtual interface. That is, it is
    // only to be invoked within a derived class print() method
    inline void
    LibraryMaterial::
    print( ostream &os ) { os << _loc; }
    接著,我們引入一個Book類,它的print函數輸出Title, Author等等。在這之前,它調用基類的print函數(LibraryMaterial::print())來顯示書本位置(MaterialLocation)。如下:
    inline void
    Book::
    print( ostream &os )
    {
    // ok, this is resolved statically,
    // and therefore is inline expanded ...
    LibraryMaterial::print();
    os << "title:" << _title
    << "author" << _author << endl;
    }
    AudioBook類,派生于Book類,并加入附加信息,比如旁述,音頻格式等等。這些東西都用它的print函數輸出。再這之前,我們需要調用Book::print()來顯示前面的信息。
    inline void
    AudioBook::
    print( ostream &os )
    {
    // ok, this is resolved statically,
    // and therefore is inline expanded ...
    Book::print();
    os << "narrator:" << _narrator << endl;
    }

   這和虛析構函數調用鏈的例子一樣,都只是最初調用的虛函數沒有被靜態決議,其它的都被原地展開。This unnamed hierarchical design pattern is significantly less effective if we never declare a virtual function to be inline.
    那么對于第二個原因中代碼膨脹的問題呢?我們來分析一下,如果我們寫下:
    LibraryMaterial *p =
    new AudioBook( "Mason & Dixon",
    "Thomas Pynchon", "Johnny Depp" );
    // ...
    p->print();
    這個print實例是內聯的嗎?不,當然不是。這樣不得不通過虛擬機制在運行期決議。這讓print實例放棄了對它的內聯聲明了嗎?也不是。這個調用轉換為下面的形式(偽代碼):
    // Pseudo C++ Code
    // Possible transformation of p->print()
    ( *p->_vptr[ 2 ] )( p );
    where 2 represents the location of print within the associated virtual function table.因為調用print是通過函數指針_vptr[2]進行的,所以,編譯器不能靜態的決定這個調用地址,并且,這個函數也不能內聯。
    當然,虛函數print的內聯實體(definition)也必須在某個地方表現出來。 即是說,至少有一個函數實體是在virtual table調用的地址原地展開的。編譯器是如何決定在何時展開這個函數實體呢?其中一個編譯(implementaion)策略是當virtual table生成的同時,生成這個函數實體。這就是說對于每一個派生類的virtual table都會生成一個函數實體。
    在一個可應用的類中有多少vitrual table會被生成呢?呵呵,這是一個好問題。C++標準中對虛函數行為進行了規定,但是沒有對函數實現進行規定。由于virtual table沒有在C++標準中進行規定,很明顯,究竟這個virtual table怎樣生成,和究竟要生成多少個vitrual table也沒有規定。多少個?當然,我們只要一個。Stroustrup的cfront編譯器,很巧妙的處理了這些情況.( Stan and Andy Koenig described the algorithm in the March 1990 C++ Report article, "Optimizing Virtual Tables in C++ Release 2.0.")
    Moreover, the C++ Standard now requires that inline functions behave as though only one definition for an inline function exists in the program even though the function may be defined in different files。新的規則要求編譯器只展開一個內聯虛函數。如果一點被廣泛采用的話,虛函數的內聯導致的代碼膨脹問題就會消失。
    [譯注:C++ Standard: 9.3.8, Member function of local class shall be defined inline in their class defination, if they are defined at all]
    ============================
    譯注:
    [a]函數調用開銷,調用基類虛函數的時候至少要經過兩次間接過程(S. B.Lippman: 《Inside the C++ Object Model》)
    一個產品類(?)
   總結:
    就是虛函數inline在調用鏈等地方很有用~
    即使沒有加入inline聲明,作為一個好編譯器,都會優化(虛析構函數)
    在很長的函數調用鏈中,最好將鏈中基類的函數inline,這樣節約開銷
    至于在什么地方inline,由編譯器決定,因為C++標準沒有規定
    新C++標準(可能沒有通過)中,規定了,inline化只對產品類有效,且只動作一次
    保證代碼不過度膨脹
    inline動作是在產品類實例化同時,和vtable生成一起。
本文地址:http://www.qingdxww.cn/thread-64043-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 深度體驗Microchip自動輔助駕駛應用方案——2025巡展開啟報名!
  • 更佳設計的解決方案——Microchip模擬開發生態系統
  • 利用模擬開發工具生態系統進行安全電路設計
  • 你仿真過嗎?使用免費的MPLAB Mindi模擬仿真器降低設計風險
  • 貿澤電子(Mouser)專區
關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产一区 在线播放 | 91久久国产青草亚洲 | 午夜影视在线视频观看免费 | 黄色在线观看国产 | 日本污视频网站 | 日韩在线视频中文字幕 | 国产一级高清视频免费看 | 亚洲第一影院 | 亚洲国产成人精品不卡青青草原 | 国产卡二卡3卡乱码免费 | 在线视频欧美精品 | 欧美另类视频在线观看 | 欧美精品成人久久网站 | 九色视频在线看 | 日韩一中文字幕 | free俄罗斯性xxxxho | 在线观看国产亚洲 | 国产片免费观看 | 亚洲国产一区视频 | 日韩视频免费在线观看 | 日韩经典欧美精品一区 | 日韩免费高清专区 | 免费国产一级特黄aa大 | 欧美成人三级网站在线观看 | 中文字幕一区二区三区久久网站 | 国产精品国产欧美综合一区 | 亚洲欧美视频 | 亚洲自拍另类 | 五月婷婷色播 | 久久这里只有精品首页 | 国产精品久久久久毛片真精品 | 国产亚洲精品不卡在线 | 午夜精品视频在线观看 | 欧美久久网 | 免费看一区二区三区 | 四虎免费在线播放 | 看草逼| 国产精品福利社 | 四虎www免费人成 | 岛国免费视频 | 国产区一区二区三区 |