C++与Java多态的区别
多態(tài)是指用父指針指向不同子類對(duì)象時(shí),調(diào)用其共有的函數(shù),不同的子類會(huì)有不同的行為。雖然C++和Java都具有多態(tài)機(jī)制,但是他們的實(shí)現(xiàn)不同,使用時(shí)的效果也會(huì)略有不同。
在C++中
- 普通函數(shù)調(diào)用:具體調(diào)用哪個(gè)方法在編譯時(shí)就可以決定(通過查找編譯器的符號(hào)表),同時(shí)在使用標(biāo)準(zhǔn)過程調(diào)用機(jī)制基礎(chǔ)上增加一個(gè)表示對(duì)象身份的指針(this指針)。
- 虛函數(shù)調(diào)用:函數(shù)調(diào)用依賴于對(duì)象的實(shí)際類型,一般地說,對(duì)象的實(shí)際類型只能在運(yùn)行時(shí)間才能確定。實(shí)現(xiàn)機(jī)制是使用virtual table(vtbls)和virtual table pointers(vptrs)。
- vtbl 是由函數(shù)指針構(gòu)成的數(shù)組或鏈表,程序中每一個(gè)class凡聲明(或繼承)虛函數(shù)者,都有一個(gè)自己的vtbl,其中的條目就是該class的各個(gè)虛函數(shù)實(shí)現(xiàn)的指針。因此必須為每一個(gè)class消耗一個(gè)vtbl空間,其大小視虛函數(shù)的個(gè)數(shù)確定。
- 凡聲明有虛函數(shù)的class,其對(duì)象都有一個(gè)隱藏的data member,用來指向class的vtbl。
- 當(dāng)多態(tài)發(fā)生時(shí),編譯器首先根據(jù)對(duì)象vptr找出其vtbl,然后找出vtbl內(nèi)對(duì)應(yīng)的函數(shù)指針,最后調(diào)用函數(shù)指針指向的函數(shù)。從而實(shí)現(xiàn)多態(tài)。
在Java中
1.C++中VTable和vptr是在編譯階段由編譯器自動(dòng)生成的,也就是說,在C++程序載入內(nèi)存以前,在.obj(.o)文件中已經(jīng)有這些結(jié)構(gòu)的信 息;Java中的方法表是由JVM生成的,因此,使用javac命令編譯后生成的.class文件中并沒有方法表的信息。只有等JVM把.class文件 載入到內(nèi)存中時(shí),才會(huì)為該.class文件動(dòng)態(tài)生成一個(gè)與之關(guān)聯(lián)的方法表,放置在JVM的方法區(qū)中。
2. C++中某個(gè)方法在VTable的索引號(hào)是在編譯階段已經(jīng)明確知道的,并不需要在運(yùn)行過程中動(dòng)態(tài)獲知;Java中的方法初始時(shí)都只是一個(gè)符號(hào),并不是 一個(gè)明確的地址,只有等到該方法被第一次調(diào)用時(shí),才會(huì)被解析成一個(gè)方法表中的偏移量,也就是說,只有在這個(gè)時(shí)候,實(shí)例方法才明確知道自己在方發(fā)表中的偏移 量了,在這之前必須經(jīng)歷一個(gè)解析的過程。
因此在構(gòu)造函數(shù)是Java會(huì)發(fā)生多態(tài),即使子類此時(shí)還沒有構(gòu)造完全(一個(gè)極難發(fā)現(xiàn)的bug)。而C++則不會(huì)發(fā)生多態(tài),待父類構(gòu)造完全,在構(gòu)造子類。
Java代碼如下:
C++代碼如下:
#include <iostream> #include <string> #include <cstring> #include <cstdlib> using namespace std; class A {public:virtual void fun(){cout<<"A"<<endl;}A(){fun();} }; class B : A {public:virtual void fun(){cout<<"B"<<endl;}B(){fun();}}; int main(int argc, char *argv[]) {B b; } //A //B可以發(fā)現(xiàn),C++構(gòu)造子類時(shí),先構(gòu)造父類,輸出A,然后在構(gòu)造自身,輸出B。而Java在構(gòu)造子類時(shí),父類并未構(gòu)造完成,但已經(jīng)可以發(fā)生多態(tài)輸出B,然后再構(gòu)造自身,輸出B。Java一般為了避免這種情況,會(huì)把fun等init()函數(shù)聲明為private或者finial。
轉(zhuǎn)載于:https://www.cnblogs.com/jostree/p/4873686.html
總結(jié)
以上是生活随笔為你收集整理的C++与Java多态的区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C语言】判断花括号{}是否匹配
- 下一篇: zabbix的安装监控windows,l