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