青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Legend

inline virtual function

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

Josée Lajoie and Stanley Lippman

------------------------------------------------------------------------------
----

[This is the last installment of a column that was being published in C++ Repo
rt magazine. Since the magazine ceased publication before this installment cou
ld be published, Josée Lajoie and Stan Lippman were gracious enough to let us
publish it on the CUJ website. — mb]

 

曾經,我們常常在談及C++時聽到一個問題:“虛函數真的應該被申明為內聯嗎?”現在,
我們很少再聽到這個問題了。反過來,我們現在聽到的是“你不應該將print()函數內聯。
將虛函數申明為內聯是錯誤的。”

這么說有兩個主要理由:(1)虛函數是在運行期判決的,而內聯是編譯期行為,所以不能從
這個(內聯)申明上得到任何好處;(2)將虛函數申明為內聯將造成此函數在可執行文件中
有多份拷貝,因此我們為一個無論如何都不能內聯的函數付出了在空間上的處罰(WQ注,
所謂的內聯函數非內聯問題)。顯然沒腦子。

只是它并不真的正確。反思一下理由(1):在很多情況下,虛函數是靜態判決的--尤其是
派生類的虛函數調用它的基類版本時。為什么會那么做?封裝。一個很好的例子是析構函
數的靜態調用鏈:基類的析構函數被派生類的析構函數觸發。除了最初的一個外,所有的
析構函數的調用都是被靜態判決的。不讓基類的虛析構函數內聯,就不能從中獲益。這會
造成很大的差別嗎?如果繼承層次很深,而又有大量的對象需要析構,(答案是)“是的
”。

另外一個例子不涉及析構函數。想像我們正在設計一個圖書館出借管理程序。我們已經將
“位置”放入抽象類LibraryMaterial。當申明print()函數為純虛函數時,我們也提供其
定義:打印出對象的位置。

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()函數會輸出書名、作者等等。在此之前,它先調用基類的L
ibraryMaterial::print()函數以顯示位置信息。例如:

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;

}

在這個例子和析構函數的例子中,派生類的虛方法遞增式地擴展其基類版本的功能,并以
調用鏈的方式被調用,只有最初一次調用是由虛體系決定的。這個沒有被命名的繼承樹設
計模式,如果從不將虛函數申明為內聯的話,顯然會有些低效。

關于理由(2)的代碼膨脹問題怎么說?好吧,思考一下。如果寫出,

LibraryMaterial *p =

new AudioBook( "Mason & Dixon",

"Thomas Pynchon", "Johnny Depp" );

// ...

p->print();

此處的print()會內聯嗎?不,當然不會。這必須在運行期經過虛體系的判決。Okay。它會
導致此處的print()函數有它自己的定義體嗎?也不會。調用被編譯為類似于這種形式:


// Pseudo C++ Code

// Possible transformation of p->print()

( *p->_vptr[ 2 ] )( p );

那個2是print()函數在相應的虛函數表中的位置。因為這個對print()的調用是通過函數指
針_vptr[2]進行的,編譯器不能靜態決定被調用函數的位置,并且函數不能被內聯。

當然,內聯的虛函數print()的定義必須出現在可執行文件中的某處,代碼才能正確執行。
也就是說,至少需要一個定義體,以便將它的地址放入虛函數表。編譯器如何決定何時產
生那一個定義體的呢?一個實現策略是在產生那類的虛函數表時同時產生那個定義體。這
意味著針對為一個類所生成的每個虛函數表實例,每個內聯的虛函數的一個實例也被產生

在可執行文件中,為一個類產生的虛函數表,實際上有多少個?啊,很好,問得好。C++標
準規定了虛函數在行為上的要求;但它沒有規定實現虛函數上的要求。既然虛函數表的存
在不是C++標準所要求的,明顯標準也沒有進一步要求如何處理虛函數表以及生成多少次。
最佳的數目當然是“一次”。例如,Stroustrup的原始cfront實現版本,在大部份情況下
聰明地達成了這一點。 (Stan和Andy Koenig描述了其算法,發表于1990年3月,C++ Repo
rt,“Optimizing Virtual Tables in C++ Release 2.0.”)

此外,C++標準現在要求內聯函數的行為要滿足好象程序中只存在一個定義體,即使這個函
數可能被定義在不同的文件中。新的規則是說滿足規定的實現版本,行為上應該好象只生
成了一個實例。一旦標準的這一點被廣泛采用,對內聯函數潛在的代碼膨脹問題的關注應
該消失了。

C++社群中存在著一個沖突:教學上需要規則表現為簡單的檢查表vs實踐中需要明智地依據
環境而運用規則。前者是對語言的復雜度的回應;后者,是對我們構造的解決方案的復雜
度的回應。何時將虛函數申明為內聯的問題,是這種沖突的一個很好的例證。

 

About the Authors
Stanley Lippman was the software Technical Director for the Firebird segment o
f Disney's Fantasia 2000. He was recently technical lead on the ToonShooter im
age capture and playback system under Linux for DreamWorks Feature Animation a
nd consulted with the Jet Propulsion Laboratory. He is currently IT Training P
rogram Chair for You-niversity.com, an e-learning training company. He can be
reached at stanleyl@you-niversity, www.you-niversity.com, and www.objectwrite.
com.

Josée Lajoie is currently doing her Master's degree in Computer Graphics at t
he University Waterloo. Previously, she was a member of the C/C++ compiler dev
elopment team at the IBM Canada Laboratory and was the chair of the core langu
age working group for the ANSI/ISO C++ Standard Committee. She can be reached
at jlajoie@cgl.uwaterloo.ca.

posted on 2007-04-26 14:55 Legend 閱讀(806) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久亚洲影院你懂的| 亚洲国产精品欧美一二99| 一区二区三区产品免费精品久久75| 欧美成人中文字幕| 亚洲精品乱码久久久久久| 亚洲高清网站| 欧美日韩在线视频一区二区| 亚洲一区二区三区精品动漫| 亚洲专区一二三| 激情成人在线视频| 亚洲黄色一区| 国产精品区免费视频| 久久成人精品| 麻豆av一区二区三区久久| 亚洲精品久久久久久下一站| 9国产精品视频| 国产综合久久久久久鬼色| 欧美+亚洲+精品+三区| 欧美国产国产综合| 欧美一区91| 玖玖玖国产精品| 亚洲欧美日韩专区| 久久福利一区| 一区二区三区视频在线观看 | 一区二区三区在线观看国产| 麻豆成人精品| 欧美精品一区二区在线播放| 亚洲欧美春色| 久久中文欧美| 欧美一区午夜视频在线观看| 欧美成人免费在线| 久久高清免费观看| 欧美日韩第一区| 久久亚洲捆绑美女| 国产精品久久久久高潮| 欧美国产第二页| 国产手机视频精品| 日韩午夜av在线| 亚洲福利一区| 亚洲欧美另类中文字幕| 夜夜嗨网站十八久久| 久久久久久久久久久久久9999| 一区二区三区色| 免费看亚洲片| 久久综合伊人77777| 国产精品无人区| 亚洲精品一区二区三区蜜桃久| 黄色av成人| 欧美一级在线视频| 欧美一区二区私人影院日本 | 久久精品亚洲一区| 欧美在线日韩精品| 欧美日韩直播| 日韩一级黄色av| 99视频在线观看一区三区| 久久久综合免费视频| 久久激情五月丁香伊人| 国产精品美女久久久久av超清| 亚洲日本免费| 亚洲精品一区二区三区不| 久久久水蜜桃av免费网站| 久久久噜噜噜| 激情久久综艺| 久久天天躁狠狠躁夜夜爽蜜月| 久久精品99国产精品酒店日本| 国产精品欧美久久| 亚洲视频一区二区| 亚洲一区中文| 国产精品久久久久国产精品日日| 亚洲乱亚洲高清| 一本一本久久| 国产精品第一页第二页第三页| 日韩小视频在线观看专区| 亚洲视频在线一区观看| 欧美日韩精品一区视频| 99亚洲视频| 性欧美xxxx大乳国产app| 国产精品自在欧美一区| 午夜久久久久久久久久一区二区| 久久国产精品一区二区三区| 狠狠综合久久| 美脚丝袜一区二区三区在线观看| 欧美成人午夜剧场免费观看| 日韩亚洲欧美成人一区| 欧美视频中文在线看| 午夜综合激情| 欧美成人黄色小视频| 亚洲美女在线看| 国产精品久久久久久久电影| 欧美在线不卡视频| 欧美国产精品v| 亚洲天堂偷拍| 国内久久视频| 欧美日韩成人| 久久大逼视频| 亚洲人成毛片在线播放女女| 亚洲综合色在线| 国内精品99| 欧美日韩不卡合集视频| 午夜在线a亚洲v天堂网2018| 欧美激情第1页| 性做久久久久久免费观看欧美| 国产在线日韩| 欧美视频一区二区三区在线观看| 性18欧美另类| 亚洲精品影院在线观看| 亚洲国产你懂的| 欧美成年人在线观看| 亚洲少妇最新在线视频| 国产精品专区一| 免费永久网站黄欧美| 亚洲影视在线| 欧美激情一区二区三区在线视频观看| 一本大道av伊人久久综合| 国产欧美在线观看一区| 欧美激情2020午夜免费观看| 欧美一区二区视频97| 亚洲毛片一区| 欧美国产欧美亚州国产日韩mv天天看完整 | 亚洲第一视频网站| 欧美资源在线| 日韩视频欧美视频| 加勒比av一区二区| 国产精品一二三四区| 欧美日韩福利视频| 欧美大片一区| 久久先锋资源| 久久久91精品国产| 午夜在线不卡| 亚洲欧美日本国产有色| 99re亚洲国产精品| 91久久国产综合久久| 欧美高清视频免费观看| 久久综合九色九九| 久久久精品午夜少妇| 欧美一区二区私人影院日本| 一区二区三区鲁丝不卡| 99re热这里只有精品视频| 亚洲国产精品电影在线观看| 国内精品亚洲| 在线欧美影院| 亚洲电影毛片| 亚洲欧洲一区二区三区久久| 亚洲福利视频在线| 亚洲茄子视频| 亚洲毛片av| 亚洲图片欧洲图片日韩av| 亚洲免费电影在线| 一本色道久久| 亚洲欧美精品suv| 欧美一区二区黄色| 欧美在线观看你懂的| 久久久国产91| 蜜臀va亚洲va欧美va天堂| 欧美成ee人免费视频| 欧美激情成人在线| 亚洲巨乳在线| 亚洲男同1069视频| 欧美在线91| 久久偷看各类wc女厕嘘嘘偷窃| 久久手机免费观看| 欧美精品色综合| 国产精品家教| 国语自产精品视频在线看一大j8| 狠狠入ady亚洲精品| 最新亚洲一区| 亚洲图片在线观看| 久久久久久久久伊人| 亚洲电影在线看| 一区二区三区日韩在线观看| 亚洲欧美国产制服动漫| 久久久久久综合网天天| 欧美国产视频在线| 国产欧美日韩精品一区| 在线观看视频亚洲| 亚洲一区视频在线| 久久字幕精品一区| 亚洲精品影院| 久久精品国产99| 欧美日韩一区二区三区免费看| 国产九区一区在线| 亚洲免费成人| 久久亚洲欧美| 一本色道久久综合亚洲精品婷婷| 欧美在线1区| 欧美日韩情趣电影| 国产一区二区按摩在线观看| 99日韩精品| 久久人91精品久久久久久不卡| 亚洲激情黄色| 久久精品99无色码中文字幕| 欧美日韩18| 亚洲黄色高清| 欧美在线免费播放| 99伊人成综合| 欧美精品少妇一区二区三区| 黑人极品videos精品欧美裸| 亚洲欧美日本日韩| 亚洲欧洲日本专区| 久久亚洲图片|