1. 什麼是多態實現多態的機制是什麼
面試官:什麼是多態呢?
豬隊友:多種形態,氣體,液體,固體~
面試官:go out! now!
到底什麼是多態呢?
允許將子類類型的指針賦值給父類類型的指針,把不同的子類對象都當作父類來看。比如你家有親屬結婚了,讓你們家派個人來參加婚禮,邀請函寫的是讓你爸來,但是實際上你去了,或者你妹妹去了,這都是可以的,因為你們代表的是你爸,但是在你們去之前他們也不知道誰會去,只知道是你們家的人。可能是你爸爸,可能是你們家的其他人代表你爸參加。這就是多態。
多態又分為 編譯時多態和運行時多態。
編譯時多態:比如重載
運行時多態:比如重寫
簡單版本:
原理也很簡單,父類或者介面定義的引用變數可以指向子類或者具體實現類的實例對象,由於程序調用方法是在運行期才動態綁定的,那麼引用變數所指向的具體實例對象在運行期才確定。所以這個對象的方法是運行期正在內存運行的這個對象的方法而不是引用變數的類型中定義的方法。
術語版本:
我們將引入java靜態分派和動態分派這個概念。
如果想深入的同學可以參考可以參考《深入理解Java虛擬機》。
參考:
https://blog.csdn.net/sunxianghuang/article/details/52280002
2. C++支持兩種類型的多態性:_________、運行時多態
(1)編譯時的多態性
編譯時的多態性是通過重載來實現的。對於非虛的成員來說,系統在編譯時,根據傳遞的參數、返回的類型等信息決定實現何種操作。
(2)運行時的多態性
運行時的多態性就是指直到系統運行時,才根據實際情況決定實現何種操作。C++中,運行時的多態性通過虛成員實現。
3. 請問 c++中 模板是 編譯時多態還是運行時多態,或者都不是,求解
是編譯時多態。所有的模板都是在編譯時產生對應的代碼,它沒有面向對象中的虛表,無法實現動態多態。
你仔細想一想,模板在應用時都必須指定確定的類型,而運行多態僅需指定一個基類就OK啦。
4. 1. 編譯時的多態性與運行時的多態性有什麼區別,他們的實現方法有什麼不同
多態從實現的角度可以劃為兩類:編譯時多態和運行時多態。
編譯時的多態性:就是在程序編譯的時候,也就是生成解決方案的時候就決定要實現什麼操作。
運行時的多態性:就是指直到系統運行時,才根據實際情況決定實現何種操作。
1、多態實現形式不同:
編譯時的多態是通過靜態連編來實現的;運行時的多態是用動態連編來實現的。
2、多態性通過方式不同:
編譯時的多態性主要是通過函數重載和運算符重載來實現的;運行時的多態性主要是通過虛函數來實現的。
(4)編譯時運行時多態擴展閱讀:
靜態多態性又稱編譯時的多態性。靜態多態性的函數調用速度快、效率高但缺乏靈活性,在程序運行前就應決定執行的函數和方法。
動態多態性的特點是:不在編譯時確定調用的是哪個函數,而是在程序運行過程中才動態地確定操作所針對的對象。又稱運行時的多態性。動態多態性是通過虛函數(virtual function)實現的。
5. 編譯時的多態性和運行時的多態性在實現方法上有何不同
我不知道你哪本書上看到的,但是,只要不是後綁定就不能稱為多態,前綁定只能稱為代碼重用,比如函數的重載、覆蓋以及一般的類繼承。
多態的關鍵特點就是:在運行時虛基類指針指向派生類對象地址,而將派生類對象地址賦值給基類指針,這就是所謂的後綁定,編譯時綁定稱為前綁定,因此多態另一個特點就是「動態「。換句話說,如果是後綁定,編譯器事先是不知道在運行時指針將指向哪一種派生類的對象,因此基類指針必須是「虛「的,虛基類中不能有任何實現只有定義,此時虛基類的作用就是一個類介面,這樣才能在編譯時「模糊」掉類型匹配原則,基類的作用只是個約定,定義了函數調用格式,而只在運行時才確定指針具體指向哪一個對象。
而所謂編譯時的多態性根本不存在,如果編譯器能確定基類指針指向哪一個派生類對象地址,就不是多態,哪怕你採用重載覆蓋或者繼承,這些編譯器已經可以預知的事情,一旦編譯完成就固定了,運行時無法更改的,比如你不能在不重新編譯的情況下增加一個重載,這就制約了程序運行時的靈活性以及可擴充性。而多態完全可以實現「熱「更新,更多的是便於程序的可擴充性。你完全可以將派生類編譯在DLL中,每當更新程序時,只要替換掉DLL而不用重新編譯全部代碼。
6. java的多態怎麼理解啊,多態有什麼用途。
多態你可以從字面上去理解,一個類表現出多種形態。它是一種編碼的技巧而不是寫代碼的格式或者方式。 要想理解多態你需要從需求入手。偽代碼例子:void method(Father instance): instance.callmethod();現在有兩個子類 girl 和 boy . 如果我傳入給method的對象是girl,那麼instance.callmethod()是否就等同於girl.callmethod(),如果傳入的是boy,就等同於boy.callmethod().但是對於程序而言,表達式一直都是 void method(Father instance): instance.callmethod();沒有改變過只不過通過傳入不同的子類對象使這樣一個表達式表現出了多種「類的形態」。這樣的現象就叫做多態。 多態在軟體結構設計上是非常重要的一個抽象意識1:多態用於解決if,else 現代的編程技巧要求對於某一個函數專注於解決一類型的事情。這就要求一個函數中要盡量的避免出現>1個if,那麼如果程序出現了分支而又要避免使用if應該怎麼辦呢。那就是多態最經常出現的場景。看下面的一個2:多態用於隱藏函數的具體內容在面向對象高度結構化的開發中,軟體根據功能的不同需要分為各種模塊分別交給不同的人開發。那麼如果同一個介面描述一類情況顯然是非常高明的。最明顯的例子就是大家最常用的System,out.println(Object).初學者可能每天都在使用這樣一個多態,但是卻不知道這個是多態。System,out.println();無論你輸入的是一個string,object,int,array,float都可以正常輸出內容。為什麼,因為所有的你string,Intege,array,Float都是Object的子類,根據填入參數的類型,System,out,println()就表現出了各種輸出功能的形態。 說了這么多希望你能夠理解。 多態可以通過介面和繼承來實現。 一個介面可以對應多個實現 (1vN : 多態的數學描述,1個形態代表多個形態)繼承:一個父類可以有多個子類 (1vN : 多態的數學描述,1個形態代表多個形態)
7. 運行時多態和編譯時多態
多態:多態的概念比較簡單,就是同一操作作用於不同的對象,可以有不同的解釋,產生不同
的執行結果。
運行時多態:重寫就是一種運行時多態。只有在運行過程中才能清楚調用的是具體的那個方法。
重寫的情況:
public class Dog {
public void bark(){
System.out.println("woof ");
}
private static class Hound extends Dog{
public void sniff(){
System.out.println("sniff ");
}
public void bark(){
System.out.println("bowl"); }
}
public static void main(String [] args){
Dog dog = new Hound();
dog.bark();
Dog dog1=new Dog();
dog1.bark();
}
}
輸出結果是:
bowl
woof
父類引用指向子類對象情況:
public class Parent{
public void call(){
sout("im Parent");
}
}
public class Son extends Parent{// 1.有類繼承或者介面實現
public void call(){// 2.子類要重寫父類的方法
sout("im Son");
}
}
public class Daughter extends Parent{// 1.有類繼承或者介面實現
public void call(){// 2.子類要重寫父類的方法
sout("im Daughter");
}
}
public class Test{
public static void main(String[] args){
Parent p = new Son(); //3.父類的引用指向子類的對象
Parent p1 = new Daughter(); //3.父類的引用指向子類的對象
p.call();
p1.call();
}
}
輸出結果是:
im son
im Daughter
同樣是 Parent 類的實例,p.call 調用的是 Son 類的實現、p1.call 調用的是 Daughter 的實現。這里因為是自己定義的,所以可以在new對像的過程中就能明白p是son,p1是daughter。但是有的時候,我們無法直觀看到new對象的過程。比如說工廠模式、Spring的ioc。所以只有在程序運行的過程才能夠清楚具體調用的是誰的方法。
編譯時多態:Java中重載就是一種編譯時多態。程序處在編譯期間,通過參數的不同來決定具體調用的是那個方法。
思考:重載一定是發生在同一個類中嗎?子類是否可重載父類的方法?