您的位置:首頁(yè) > 學(xué)生信息 > 學(xué)習(xí)心得
來(lái)源:北大青鳥(niǎo)飛迅校區(qū)|發(fā)布時(shí)間:2013-05-05 11:24:38
C++中,如果父類(lèi)中的函數(shù)前邊標(biāo)有virtual,才顯現(xiàn)出多態(tài)。
如果父類(lèi)func是virtual的,則
Super *p =new Sub();
p->func(); // 調(diào)用子類(lèi)的func
如果不是virtual的,p->func將調(diào)用父類(lèi)原來(lái)的函數(shù)。
Java中,不管寫(xiě)不寫(xiě)virtual都是多態(tài)的,子類(lèi)的同名函數(shù)會(huì)override父類(lèi)的。與C++很不同的是,初始化的過(guò)程也不相同。在還未初始化子類(lèi)的時(shí)候,子類(lèi)的同名函數(shù)就已經(jīng)覆蓋了父類(lèi)的了。例如:
public class Super {
public Super() {
System.out.println("super constructor...");
m();
}
protected void m() {
System.out.println("test");
}
}
public class Sub extends Super{
private final Date date;
public Sub(){
System.out.println("sub constructor...");
date=new Date();}
public void m()
{
System.out.println(date);
}
public static void main(String[] args)
{
Super test1=new Sub();
test1.m(); //執(zhí)行的子類(lèi)的m
}
}
new Sub的時(shí)候首先調(diào)用Super,Super構(gòu)造函數(shù)調(diào)用的m就已經(jīng)是被Sub覆蓋的m,所以會(huì)print出null(因?yàn)槿掌跊](méi)有初始化)。所以在java中,不要在父類(lèi)構(gòu)造函數(shù)中調(diào)用外部可改變的方法,有可能會(huì)輸出可改變方法中還沒(méi)初始化的東西。
但是,同樣的初始化在C++中,初始化一個(gè)子類(lèi)的時(shí)候,父類(lèi)調(diào)用的m,是父類(lèi)自己的m,不會(huì)調(diào)用子類(lèi)的。
——————
另外一個(gè)參考也很有用:http://7880.com/info/Article-51701560.html,如下:
C++和java中多態(tài)機(jī)制的異同
以前我有個(gè)錯(cuò)誤的觀點(diǎn):即使在C++和java中多態(tài)性的實(shí)現(xiàn)機(jī)制可能不同,但它們的表現(xiàn)形式應(yīng)該相同,也就是說(shuō)如果代碼結(jié)構(gòu)相同,那么執(zhí)行結(jié)果也應(yīng)該相同?上屡c愿違,事情并不總是你想象中的那樣子。(在看下文以前,你最好先考慮一下這個(gè)問(wèn)題,你有什么看法呢?)
ok,讓我們進(jìn)入正題。
首先本文不討論面向?qū)ο缶幊痰幕靖拍,如封裝、繼承和數(shù)據(jù)抽象等,這方面的資料現(xiàn)在應(yīng)該多如牛毛,只是稍微提一下多態(tài)性的概念。根據(jù)Bjarne Stoustrup的說(shuō)法,多態(tài)性其實(shí)就是方法調(diào)用的機(jī)制,也就是說(shuō)當(dāng)在編譯時(shí)無(wú)法確定一個(gè)對(duì)象的實(shí)際類(lèi)型時(shí),應(yīng)當(dāng)能夠在運(yùn)行時(shí)基于對(duì)象的實(shí)際類(lèi)型來(lái)決定調(diào)用的具體方法(動(dòng)態(tài)綁定)。
我們先來(lái)看一下在C++中的函數(shù)調(diào)用方式:
Ø 普通函數(shù)調(diào)用:具體調(diào)用哪個(gè)方法在編譯時(shí)間就可以決定(通過(guò)查找編譯器的符號(hào)表),同時(shí)在使用標(biāo)準(zhǔn)過(guò)程調(diào)用機(jī)制基礎(chǔ)上增加一個(gè)表示對(duì)象身份的指針(this指針)。
Ø 虛函數(shù)調(diào)用:函數(shù)調(diào)用依賴(lài)于對(duì)象的實(shí)際類(lèi)型,一般地說(shuō),對(duì)象的實(shí)際類(lèi)型只能在運(yùn)行時(shí)間才能確定。虛函數(shù)一般要有兩個(gè)步驟來(lái)支持,首先每一個(gè)類(lèi)產(chǎn)生出一堆指向虛函數(shù)的指針,放在表格中,這個(gè)表格就叫虛函數(shù)表(virtual table);然后每一個(gè)類(lèi)對(duì)象(class object)會(huì)添加一個(gè)指向相關(guān)虛函數(shù)表(virtual table)的指針,通常這個(gè)指針叫做vptr。
在java中又是如何的呢?恩,區(qū)別還是滿(mǎn)大的。在java虛擬機(jī)中,類(lèi)實(shí)例的引用就是指向一個(gè)句柄(handle)的指針,而該句柄(handle)其實(shí)是一對(duì)指針:其中一個(gè)指針指向一張表,該表格包含了對(duì)象的方法列表以及一個(gè)指向類(lèi)對(duì)象(表示對(duì)象類(lèi)型)的指針;另一個(gè)指針指向一塊內(nèi)存地址,該內(nèi)存是從java堆中為對(duì)象的數(shù)據(jù)而分配出來(lái)的。
唔,你要說(shuō)了,好象差不多嘛,不是都要維護(hù)一張函數(shù)表嗎?別急,讓我們先看一下例子,這樣你就能更好的理解它們之間的區(qū)別到底有多大了。
下面是C++和java的例子,不看后面的答案,你能夠正確說(shuō)出它們的執(zhí)行結(jié)果嗎?
例1:C++
class Base
{
public:
Base()
{
init();
}
virtual ~Base() {}
public:
virtual void do_init()
{
init();
}
protected:
virtual void init()
{
cout << "in Base::init()" << endl;
}
};
class Derived : public Base
{
public:
Derived()
{
init();
}
protected:
void init()
{
cout << "in Derived::init()" << endl;
}
};
int main(int argc, char* argv[])
{
Base* pb;
pb = new Derived();
delete pb;
return 0;
}
例2:java
class Base
{
public Base()
{
init();
}
protected void init()
{
System.out.println("in Base::init()");
}
public void do_init()
{
init();
}
}
class Derived extends Base
{
public Derived()
{
init();
}
protected void init()
{
System.out.println("in Derived::init()");
}
}
public class Test
{
public static void main(String[] args)
全程面授,不高薪都難
申請(qǐng)成功后,我們將在24小時(shí)內(nèi)與您聯(lián)系
招生熱線: 4008-0731-86 / 0731-82186801
學(xué)校地址: 長(zhǎng)沙市天心區(qū)團(tuán)結(jié)路6號(hào)
Copyright © 2006 | 湖南大計(jì)信息科技有限公司 版權(quán)所有
湘ICP備14017520號(hào)-3