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

sherrylso

C++博客 首頁 新隨筆 聯(lián)系 聚合 管理
  18 Posts :: 0 Stories :: 124 Comments :: 0 Trackbacks

四、c++中的多態(tài)規(guī)則。
一) c++中函數(shù)動(dòng)態(tài)綁定規(guī)則。
看下面的例子:

class Window
{

public:
  virtual 
void  oops()
  
{
    cout
<<"Window oops"<<endl;
  }

public:
  
int height;
  
int width;
}
;
class TextWindow : public Window
{

public:
  virtual 
void  oops()
  
{
    cout
<<"TextWindow oops"<<cursorLocation<<endl;
  }

public:
  
int cursorLocation;
}
;

main()
{
  Window win;
  Window
* tWin;
  TextWindow 
* tWinPtr;

  tWinPtr 
= new TextWindow;
  tWin 
= tWinPtr;
  
  win.oops();
  tWin
->oops();
}


類TextWindow繼承與類Window。我想程序運(yùn)行的結(jié)果,大多數(shù)熟悉C++的人都會(huì)知道,
win.oops()最終調(diào)用的是父類oops函數(shù),而tWin->oops()調(diào)用的是子類TextWindow的函數(shù)。
通過這個(gè)例子,我們先總結(jié)一下c++中的多態(tài)調(diào)用規(guī)則
第一、對(duì)于指針和引用類型,當(dāng)消息調(diào)用的成員函數(shù)有可能被重寫時(shí),最終被選擇調(diào)用的成員函數(shù)由消息接收者的動(dòng)態(tài)類型確定(注意:在OO概念中,對(duì)某個(gè)對(duì)象成員函數(shù)進(jìn)行調(diào)用,常常稱為給該對(duì)象發(fā)送消息,該對(duì)象就是消息的接收者)。
      如上例:tWin->oops(),由于tWin的動(dòng)態(tài)類型是子類TextWindow,而不是Windows,所以tWin->oops()調(diào)用的是子類TextWindow的函數(shù)。
二、對(duì)于其它的變量,對(duì)虛擬函數(shù)調(diào)用綁定完全由該變量的靜態(tài)類型確定(即該變量的聲明),而不是該變量的真實(shí)類型確定。
     如上例:win.oops(),由于win的聲明類型為Window類,所以其結(jié)果調(diào)用的是父類oops函數(shù)。
二) 探討。
     接下來,我們要看的問題是,在c++中,為什么對(duì)于多態(tài)規(guī)則(或者說是動(dòng)態(tài)函數(shù)綁定規(guī)則),做出了兩中不同的劃分,即:只有指針與引用類型,才進(jìn)行函數(shù)的后期動(dòng)態(tài)綁定,也就是多態(tài)。這或許也是許多c++初學(xué)者非常迷惑的地方。這種規(guī)則的不一致性,的確給c++的語法造成一定的復(fù)雜性。而這在Java,或者C#中是沒有的,后面我們會(huì)涉及到。
      我們先來看例子。 

void f()
{
  Window  win;
  Window
* tWinPtr;
  
  tWinPtr 
= new TextWindow;
  win     
= *tWinPtr;//what's problem happen
   
  win.oops(); 
//what's problem happen
  tWinPtr->oops();
}


      在這里,如果我們假設(shè),c++的函數(shù)動(dòng)態(tài)綁定規(guī)則是一致的,看看會(huì)發(fā)生什么問題???
      現(xiàn)在win被聲明為Window類型,然而其真實(shí)的類型為TextWindow(因?yàn)閣in=*tWinPtr),由于我們的假設(shè),win現(xiàn)在是允許進(jìn)行動(dòng)態(tài)函數(shù)綁定的,所以當(dāng)執(zhí)行win.oops()時(shí),實(shí)際上是調(diào)用子類TextWindow的成員函數(shù)。
     現(xiàn)在,我們有必要來審視一下win變量的內(nèi)存布局。由于win變量是在棧上聲明的變量,其內(nèi)存也是從棧進(jìn)行分配(這是c++從c語言那里繼承過來的優(yōu)良特質(zhì),從棧上分配內(nèi)存空間比動(dòng)態(tài)分配內(nèi)存有更好的執(zhí)行速度),c++標(biāo)準(zhǔn)規(guī)定:給win變量分配內(nèi)存空間的大小,由其靜態(tài)的類型確定,即應(yīng)該是Window類所使用的內(nèi)存空間大小。在這種情況下,當(dāng)執(zhí)行win=*tWinPtr時(shí),什么會(huì)發(fā)生?如下圖:

在默認(rèn)的拷貝構(gòu)造函數(shù)情況下,信息會(huì)出現(xiàn)丟失,這就是著名的slicing off現(xiàn)象。結(jié)果,變量cursorLocation在win的內(nèi)存空間里丟失了。然而,問題是:在我們假設(shè)下,我們要求win.oops()導(dǎo)致TextWindow的成員函數(shù)調(diào)用,而在這個(gè)函數(shù)中,訪問到的cursorLocation變量是不存在!win.oops()調(diào)用將導(dǎo)致內(nèi)存違例!
      到這里,我們可以總結(jié)一下:c++標(biāo)準(zhǔn)基于的其特定的內(nèi)存分配規(guī)則,給出了以上,我們?cè)谇耙还?jié)總結(jié)出的函數(shù)動(dòng)態(tài)綁定規(guī)則。
三) 深入。
      當(dāng)然,我們也可以說,c++也可以通過改變其內(nèi)存分配規(guī)則,來給出一個(gè)一致性的函數(shù)動(dòng)態(tài)綁定規(guī)則。比如:可以考慮在給win變量分配內(nèi)存空間時(shí),考慮其所有子類需求,然后分配最大數(shù)量的內(nèi)存空間給win變量。這種做法可行性很差,對(duì)于編譯器而言,需要掃描整個(gè)程序(確定該類的所有子類),才能確定最大的內(nèi)存空間是多少。在使用類庫或者框架的情況下,會(huì)引起整個(gè)類庫,框架的重新編譯,這是得不償失的!而這種做法,在oo的語言中,基本上是沒有的。這也是c++不得不基于其現(xiàn)有的內(nèi)存管理機(jī)制,而對(duì)多態(tài)規(guī)則作出的不一致的解釋。
    對(duì)于這個(gè)c++現(xiàn)有的內(nèi)存管理機(jī)制,我們?nèi)绻麖牧硗饨嵌热ダ斫獾脑?是很合理的。當(dāng)win=*tWinPtr發(fā)生
時(shí),我們可以類似地認(rèn)為:好比一個(gè)float類型的數(shù)賦給了一個(gè)interger類型的變量,其結(jié)果當(dāng)然是float的值被截?cái)嗔恕?br>    我們?cè)賮砜雌渌Z言,Java(或者C#)是怎么解決的。
    最重要的一點(diǎn)是,在Java(C#)中只有引用的概念,所以在棧上聲明的類的變量,只需要分配一個(gè)指針大小的內(nèi)存空間就行了,而不需要給該變量分配空間來保存變量?jī)?nèi)容本身,這其實(shí)就是我們現(xiàn)在看到的c++中指針和引用的情況。
    

 

posted on 2008-01-05 23:12 愛上龍卷風(fēng) 閱讀(3197) 評(píng)論(8)  編輯 收藏 引用

Feedback

# re: c語法背后的故事(二) [未登錄] 2008-01-06 12:21 ZZZ
是有點(diǎn)晦澀  回復(fù)  更多評(píng)論
  

# re: c++晦澀語法背后的故事(二) 2008-01-07 22:53 abettor.org
看來這個(gè)容易理解一些,呵呵。  回復(fù)  更多評(píng)論
  

# re: c++晦澀語法背后的故事(二) [未登錄] 2008-01-10 11:10 Composition
sherrylso兄,
void f()
{
Window win;
Window* tWinPtr;

tWinPtr = new TextWindow;
win = *tWinPtr;//what's problem happen

win.oops(); //what's problem happen
tWinPtr->oops();
}
中win.oops(); 仍然會(huì)調(diào)用父類的方法,因?yàn)榫幾g器生成的拷貝構(gòu)造函數(shù)不會(huì)拷貝vptr。希望你check一下。
這里僅僅切割了子對(duì)象,但是切割后的對(duì)象是合法的父對(duì)象,除非你的設(shè)計(jì)不合理,違反了LSP。  回復(fù)  更多評(píng)論
  

# re: c++晦澀語法背后的故事(二) 2008-01-11 22:04 愛上龍卷風(fēng)
@Composition
我的論述的前提是:“假設(shè):c++的函數(shù)動(dòng)態(tài)綁定規(guī)則是一致的“
搞不清楚你的觀點(diǎn)是什么?
  回復(fù)  更多評(píng)論
  

# re: c++晦澀語法背后的故事(二) 2008-01-14 13:35 Composition
我的意思是不管子對(duì)象怎么切割,win.oops(); 永遠(yuǎn)會(huì)調(diào)用父類的函數(shù),絕不會(huì)因?yàn)榍懈钫{(diào)用子類的方法。既然不調(diào)用子類的方法,自然不會(huì)出錯(cuò)。你可以在編譯器實(shí)驗(yàn)一下,你這個(gè)例子會(huì)輸出Window oops xxx,沒有錯(cuò)誤。
不管怎么假設(shè),通過對(duì)象調(diào)用成員函數(shù)都是編譯時(shí)綁定,永遠(yuǎn)不可能調(diào)用到子類的成員函數(shù)。
win = *tWinPtr;這句會(huì)調(diào)用Window的拷貝構(gòu)造(編譯器生成),但是拷貝構(gòu)造不會(huì)拷貝對(duì)象的vptr。而且就算拷貝了,通過對(duì)象調(diào)用成員函數(shù)也不通過vptr找vtable,而是直接調(diào)用對(duì)象類型對(duì)應(yīng)到成員函數(shù)(編譯后成為全局函數(shù))。你這里假設(shè)“c++的函數(shù)動(dòng)態(tài)綁定規(guī)則是一致的”,但別忘了,vptr不拷貝,這是C++實(shí)現(xiàn)機(jī)制,怎么調(diào)用都是父類的成員函數(shù),不會(huì)有多態(tài)。
如果你做出拷貝構(gòu)造會(huì)拷貝vptr+對(duì)象調(diào)用會(huì)查找vtable的假設(shè),那么你的論述應(yīng)該合理。但是這么假設(shè)個(gè)人認(rèn)為意義不大。  回復(fù)  更多評(píng)論
  

# re: c++晦澀語法背后的故事(二) 2008-01-14 21:39 愛上龍卷風(fēng)
@Composition
1) 首先,我要論述的是多態(tài)規(guī)則,不是只有C++有。很多面向?qū)ο蟮恼Z言都有的特性。Java, C#, Smalltalk。你不必要局限于C++本身。
2) 其次,你說的,我都贊同,這就是c++的內(nèi)存管理機(jī)制。
3) 基于c++的內(nèi)存管理機(jī)制,推出了現(xiàn)有的C++多態(tài)規(guī)則。
4)我是在討論,C++語法為什么復(fù)雜的背后原因。也就是怎么去更好地理解現(xiàn)行的語法。
  回復(fù)  更多評(píng)論
  

# re: c++晦澀語法背后的故事(二) 2008-01-14 21:41 愛上龍卷風(fēng)
@Composition
再者,如果C++改變了現(xiàn)有的內(nèi)存管理機(jī)制,即我提到的:可以考慮在給win變量分配內(nèi)存空間時(shí),考慮其所有子類需求,然后分配最大數(shù)量的內(nèi)存空間給win變量。
是可以做到多態(tài)規(guī)則的一致性  回復(fù)  更多評(píng)論
  

# re: c++晦澀語法背后的故事(二) 2008-01-15 12:14 Composition
我明白你的意思了,不過我也沒有完全拘泥于C++,但是C++的多態(tài)實(shí)現(xiàn)確實(shí)與其他語言很不同。如Python,Ruby之類語言通過給類建立哈希表來實(shí)現(xiàn)多態(tài)。Java,C#之類應(yīng)該是通過元數(shù)據(jù)。而且只有C++才有切割問題,其他語言在堆上分配就不存在切割了。
至于你的例子f()我覺得可以改成如下的例子更能說明問題,而且也不必做過多假設(shè):
void f()
{
Window win;
TextWindow textWin;
Window* tWinPtr;

tWinPtr = new TextWindow;
memcpy(reinterpret_cast<char*>(tWinPtr) + 4,
reinterpret_cast<char*>(&win) + 4,
sizeof(win) - 4); //don't change vptr

tWinPtr->oops(); //what's problem happen
}
這個(gè)例子會(huì)發(fā)生錯(cuò)誤,即使運(yùn)行不出錯(cuò),邏輯也是錯(cuò)的。
至于你對(duì)“可以考慮在給win變量分配內(nèi)存空間時(shí),考慮其所有子類需求,然后分配最大數(shù)量的內(nèi)存空間給win變量?!钡恼撌龊芡笍?,我同意。  回復(fù)  更多評(píng)論
  


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   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精品久久久久久9| 91久久精品国产91久久| 亚洲免费视频在线观看| 亚洲男人的天堂在线aⅴ视频| 国产毛片久久| 亚洲第一精品在线| 国产精品推荐精品| 欧美国产一区二区| 国产毛片一区| 亚洲精品乱码久久久久久蜜桃麻豆 | 极品中文字幕一区| 欧美大片在线看| 国产亚洲欧美aaaa| 日韩一级免费| 亚洲肉体裸体xxxx137| 亚洲影院一区| 午夜视频在线观看一区| 欧美福利小视频| 蜜臀av性久久久久蜜臀aⅴ| 欧美性片在线观看| 一区二区三区四区五区精品视频| 国产综合av| 久久精品官网| 久久精品亚洲一区二区三区浴池| 欧美日韩另类丝袜其他| 亚洲精品欧美在线| 日韩亚洲精品视频| 欧美日韩一区二区三区在线| 亚洲黄色大片| 亚洲天天影视| 国产欧美日韩伦理| 欧美在线视频一区二区三区| 久久精品二区三区| 国产偷自视频区视频一区二区| 一本不卡影院| 久久亚洲精品网站| 亚洲片在线资源| 亚洲国产精品一区二区www| 亚洲国产另类久久精品| 欧美精品日韩三级| 亚洲午夜视频| 欧美大尺度在线| 亚洲一区二区三区精品视频| 国产精品稀缺呦系列在线| 性欧美1819sex性高清| 亚洲福利在线观看| 欧美在线播放| 欧美激情精品久久久| 亚洲第一区色| 老司机午夜精品视频| 欧美激情bt| 一区二区三区在线观看视频 | 午夜激情亚洲| 蜜臀99久久精品久久久久久软件| 亚洲免费成人av| 影院欧美亚洲| 国产伦精品一区二区三区视频孕妇| 欧美一区二区三区日韩视频| 亚洲精品一区久久久久久| 久久xxxx精品视频| 先锋影音国产一区| 亚洲视频电影图片偷拍一区| 在线视频观看日韩| 狠狠v欧美v日韩v亚洲ⅴ| 久久免费视频一区| 日韩视频一区二区三区在线播放免费观看| 亚洲一区二区毛片| 亚洲欧美激情视频| 亚洲午夜高清视频| 亚洲精品视频免费在线观看| 亚洲国产精品ⅴa在线观看| 精品999在线播放| 亚洲高清视频一区| 亚洲另类自拍| 亚洲影院污污.| 另类图片综合电影| 欧美精品一区二区三区视频| 欧美日本韩国| 国产欧美精品一区aⅴ影院| 国产欧美日韩亚州综合| 1204国产成人精品视频| 亚洲三级视频在线观看| 亚洲午夜一区二区三区| 亚洲欧洲av一区二区| 久久亚洲精品网站| 亚洲美女网站| 久久精品视频免费播放| 欧美激情中文字幕在线| 国产精品一区二区久久精品| 在线观看视频亚洲| 午夜免费在线观看精品视频| 麻豆成人综合网| 一区二区三区色| 久热爱精品视频线路一| 国产热re99久久6国产精品| 亚洲成人影音| 久久在线91| 亚洲中字在线| 欧美日韩国产美女| 亚洲国产欧美一区| 久久久久九九九| 亚洲一区二区三区在线播放| 你懂的亚洲视频| 亚洲日韩欧美视频一区| 欧美成人激情视频免费观看| 午夜激情一区| 国语自产精品视频在线看8查询8 | 久久精品国产亚洲精品| 亚洲天天影视| 国产一区清纯| 免费亚洲一区二区| 欧美精品一区二区高清在线观看| 在线精品观看| 亚洲欧洲久久| 欧美色网一区二区| 久久高清国产| 久久久久国内| 你懂的一区二区| 日韩性生活视频| 亚洲欧美在线观看| 亚洲高清影视| 日韩亚洲欧美高清| 国产日韩欧美在线看| 麻豆精品网站| 欧美色道久久88综合亚洲精品| 亚洲综合999| 久久久久中文| 久久大综合网| 欧美高清视频一区二区| 久久大逼视频| 国产精品www色诱视频| 欧美www视频| 国产精品亚洲成人| 99热免费精品| 亚洲国产欧美日韩精品| 亚洲午夜一区| 亚洲免费人成在线视频观看| 久久久夜精品| 麻豆精品精品国产自在97香蕉| 国产精品美女久久久久av超清| 牛人盗摄一区二区三区视频| 国产一区二区三区成人欧美日韩在线观看 | 免费美女久久99| 欧美成人黑人xx视频免费观看| 国产一区二区久久精品| 一区二区三区四区五区精品视频| 美女黄毛**国产精品啪啪| 亚洲天堂久久| 国产亚洲永久域名| 久久国产精品久久w女人spa| 久久野战av| 亚洲精品视频在线播放| 欧美韩日亚洲| 午夜久久资源| 亚洲激情综合| 亚洲欧美一区二区激情| 黄色成人精品网站| 欧美激情精品久久久久久蜜臀 | 亚洲国产三级在线| 欧美日韩国产首页| 亚洲午夜三级在线| 美女视频黄a大片欧美| 亚洲精选91| 国产一区二区三区的电影 | 欧美专区日韩视频| 亚洲精品日韩一| 久久综合激情| 亚久久调教视频| 亚洲国产一区二区a毛片| 国产裸体写真av一区二区| 免费一级欧美片在线播放| 午夜一级在线看亚洲| 亚洲精品一二三区| 亚洲激情电影中文字幕| 女人色偷偷aa久久天堂| 久久er精品视频| 欧美在线www| 久久激情视频久久| 久久成人亚洲| 久久久www成人免费毛片麻豆| 亚洲无限av看| 亚欧成人在线| 久久婷婷麻豆| 欧美在线免费观看视频| 亚洲国产经典视频| 欧美日韩免费观看一区| 久久精品国产免费观看| 欧美成人一区二免费视频软件| 亚洲福利专区| 国产一区91| 欧美激情影音先锋| 免费高清在线一区| 久久天天躁狠狠躁夜夜av| 久久亚洲一区二区三区四区| 久久精品夜色噜噜亚洲aⅴ| 亚洲综合视频网| 欧美一区午夜视频在线观看| 午夜精品久久久久久久久久久久久| 亚洲午夜av|