1. 程式人生 > >子類繼承父類的虛擬函式呼叫

子類繼承父類的虛擬函式呼叫

父類:Father

子類:Son

1.  Father* fa=new Son()

    例項1:

#include<iostream>
using namespace std;

class Father{
public:
	Father(){
		cout << "this is the Father constructor!" << endl;
	}
	void watchTv(){
		cout << "Father is watching tv!" << endl;
	}
	virtual void say(){
		cout << "Father is saying!" << endl;
	}
};

class Son :public Father{
public:
	Son(){
		cout << "this is the Son constructor!" << endl;
	}
	void watchTv(){
		cout << "Son is watching tv!" << endl;
	}
	void say(){
		cout << "Son is saying!" << endl;
	}
};

int main(){
	Father* fa = new Son();
	fa->watchTv();
	fa->say();
	system("pause");
	return 0;
}
執行結果:


結果分析:

1.首先執行程式碼 Father* fa=new Son();,會首先呼叫父類建構函式,再呼叫子類建構函式,所以第一、第二行如圖所示;

2.執行程式碼fa->watchTv(),根據fa的型別,因為是Father型別的,所以會先檢視Father類中的watchTv函式,因為不是虛擬函式,所以直接呼叫,結果如第三行所示;

3.執行程式碼fa->say(),根據fa的型別,因為是Father型別的,所以先檢視Father類中的say函式,因為是虛擬函式,所以會檢視虛擬函式表,檢視實現例項,找到子類Son有實現虛擬函式say,所以會呼叫子類Son的say函式,結果如第四行所示。

  例項2: 在建構函式中呼叫虛擬函式

#include<iostream>
#include<string>
using namespace std;
class Father{
public:
	Father():val("HunanTv"){
		cout << "this is the Father constructor!" << endl;
		say();
	}
	virtual void watchTv(){
		cout << "Father is watching tv:" <<val<< endl;
	}
	void say(){
		cout << "Father is saying to watchTv!" << endl;
		watchTv();
	}
	string val;
};

class Son :public Father{
public:
	Son(){
		cout << "this is the Son constructor!" << endl;
		say();
	}
	virtual void watchTv(){
		val = "GuangdongTv";
		cout << "Son is watching tv:"<<val << endl;
	}
};

int main(){
	Father* fa = new Son();
	fa->say();
	system("pause");
	return 0;
}

執行結果:


結果分析:

1.執行程式碼Father* fa=new Son(),會先呼叫父類建構函式,父類建構函式中會執行以下操作:a)首先給變數val賦值為“HunanTv",其次,呼叫函式say(),此時會輸出前兩行內容;b)因為say()函式會呼叫虛擬函式watchTv(),而且在子類中有watchTv的例項實現,但是根據輸出結果第三行發現,呼叫的還是父類的虛擬函式,為什麼呢?因為,父類建構函式中呼叫虛擬函式,表現的虛擬函式為父類的虛擬函式,所以結果為第三行的顯示;c)父類建構函式呼叫完後,執行子類建構函式,因為子類沒有定義say()函式,所以呼叫繼承自父類的say()函式,所以輸出結果為第四、第五行;d)say函式呼叫虛擬函式watchTv(),因為是在子類Son的建構函式中呼叫虛擬函式,所以呼叫的是子類的watchTv,所以輸出結果如第六行所示;e)執行完子類構建後,執行fa->say();,首先看fa的型別,所以呼叫父類的say(),say()呼叫虛擬函式watchTv時,因為watchTv在子類中有例項實現,所以會呼叫子類的watchTv,所以輸出結果如第七、第八行所示。

總結:

1.當在建構函式中呼叫虛擬函式時,虛擬函式表現為該類中虛擬函式的行為,即父類建構函式呼叫虛擬函式,則虛擬函式為父類中的虛擬函式;子類建構函式中呼叫虛擬函式,則呼叫的是子類中的虛擬函式;

2.如果不是在建構函式中呼叫虛擬函式,則會首先檢視虛擬函式表,如果有例項實現,則呼叫例項。比如:父類中有虛擬函式watchTv,則呼叫父類中watchTv時,則因為子類實現了watchTv,則呼叫子類的watchTv。

相關推薦

繼承虛擬函式呼叫

父類:Father 子類:Son 1.  Father* fa=new Son()     例項1: #include<iostream> using namespace std; class Father{ public: Father(){ cou

c++繼承函式呼叫特性原理以及與java的對比

c++ c++中子類繼承了父類,子類物件的函式和變數會接著新增在父類物件的記憶體後面,以此類推。。。 如果c++中父類的那個變數或者函式宣告為virtual虛擬函式,那麼子類物件的同名函式就直接覆蓋了(即在記憶體中真正的覆蓋,父類的這個函式已經不在了)父類物件的這個函式 如

關於繼承呼叫方法的問題

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class ParentClass { public String m

繼承,重寫方法,運用多型時呼叫重寫的方法時呼叫的還是呼叫的?

package 第五天; public class Person { public void say() { System.out.println("我是Person的say方法"); } } 子類Student如下: package 第五天; publ

Java繼承呼叫介面

父類程式碼: 功能:定義一個vehicle類及其中的set函式及get函式 public class vehicle { private double speed; private String name; private String color; publi

繼承後想要擴展方法

保留 回調 gen obj pcl logs col 父類 sel 1 >>> class PClass(object): 2 def setInfo(self,sex=‘Male‘): 3 self.gender = se

Java 繼承成員中的問題

subclass 情況 討論 就會 之前 測試 public 測試結果 string   之前搞錯了,變量沒有“重寫”一說,只有方法才能被“重寫”。如果我們在子類中聲明了一個和父類中一樣的變量,那麽實際的情況是,子類的內存堆中會有類型和名字都相同的兩個變量。   現在考慮一

python 繼承__init__(轉載)

elf lpad pla 最好 就是 main 代碼 borde wid 轉載: http://www.jb51.net/article/100195.htm 前言 使用Python寫過面向對象的代碼的同學,可能對 __init__ 方法已經非常熟悉了,__init__

繼承中的構造器

gen 向上轉型 類構造 復制 使用 article col 成員 ring 子類繼承父類,子類構造器會默認調用super()(無論構造器中是否寫有super()),用於初始化父類成員.同時當父類中存在有參構造器時,必須提供無參構造器,子類構造器中並不會自動繼承有參構造器,

Java繼承的載入順序,看著一篇就夠了

1. 程式碼 package parent; public class Child extends Father { static { System.out.println("

java中的繼承-繼承的許可權問題

                                                java中的繼承         Java語言面向物件有三大特性:封裝、繼承、多型。其中的繼承,描述了一

java中子繼承呼叫利用繼承方法時呼叫this

package cn.itcast.test1; class Parent{     public Object getObject(){         return this;     } } c

python 繼承的__init__方法

父類: 1 class A(object): 2 def __init__(self, name): 3 self.name = name 4 print("父類name:", self.name) 5 6 def getName(self): 7

java中子繼承時是否繼承建構函式呢?

java繼承中對建構函式是不繼承的。 以下是例子:  public class FatherClass { public FatherClass() {       System.out.println(100); }  public FatherClass(int age)

繼承的輸出結果

public class A { static{ System.out.println("static in class A"); } public A(){ System.out.println("class A"); }

JAVA基礎-繼承例項化物件過程

class Parent {     // 靜態變數     public static String p_StaticField = "父類--靜態變數";     // 變數(其實這用物件更好能體同這一點,如專門寫一個類的例項)        //如果這個變數放在初始化塊的後面,是會報錯的,因為你根本沒

繼承,new 一個子物件的過程(待完善)

父類 public class JVMBase { public static String staticName="父類靜態變數"; public String name="父類非靜

java中序列化之繼承序列化

當一個父類實現Serializable介面後,他的子類都將自動的實現序列化。    以下驗證了這一點:  package Serial; import java.io.Serializable;  public class SuperC implements Serializable {//父類實現了序列化

實現Parcelable介面,繼承需要實現的操作

show me the code public class A implements Parcelable { public String str; public boolea

關於學習Kotlin繼承,成員屬性Override時候需要注意的問題

最近在學習Kotlin這門語言,作為一個java程式設計師兼android程式設計師,Kotlin又在17年強勢被google推崇為android官方開發語言之一,這就意味著,過去基於java語言的android開發人員,很有必要去掌握Kotlin這門語言,當然我這裡不去談論