關於多態的小結

  1. 什麼是多態?

    多態按照字面的意思就是“多種狀態 ”的意思。在C++中多態有着更廣泛的含義。下面着重介紹C++語言中關於多態的一些知識點。

  2. C++中多態分爲靜態多態和動態多態。靜態多態通過函數重載和泛型編程實現。動態多態通過虛函數來實現。參照下圖:

    wKiom1cXA6ShkMMEAAA7M48LKTc565.png

  3. 靜態多態:

      編譯器在編譯期間完成的,編譯器根據函數實參的類型(可能會進行隱式類型轉換),可推斷出要調用那個函數,如果有對應的函數就調用該函數,否則出現編譯錯誤。

int Add(int a1, int a2)
{
   return a1 + a2;
}
double Add(double d1, double d2)
{
   return d1 + d2;
}
int main()
{
  cout << Add(10, 20) << endl;//調用第一個函數
  cout << Add(12.3, 34.5) << endl;//調用第二個函數
  return 0;
}

以上例子是通過函數重載實現靜態多態的。

4. 動態多態:

  動態綁定:在程序執行期間(非編譯期)判斷所引用對象的實際類型,根據其實際類型調用相應的方 法。

  使用virtual關鍵字修飾函數時,指明該函數爲虛函數,派生類需要重新實現,編譯器將實現動態綁定。 

class Base
{
public:
	virtual void FunTest1()//虛函數
	{
		cout << "Base::FunTest1()" << endl;
	}
	virtual void FunTest2()//虛函數
	{
		cout << "Base::FunTest2()" << endl;
	}
};

class Derived:public Base
{
public:
	void FunTest1()//對基類的基類虛函數FunTest1()進行重寫
	{
		cout << "Derived::FunTest1()" << endl;
	}
	void FunTest3()
	{
		cout << "Derived::FunTest3()" << endl;
	}
	void FunTest4()
	{
		cout << "Derived::FunTest4()" << endl;
	}
};

int main()
{
	Base b;
	Derived d;
	b.FunTest1();
	b.FunTest2();
	d.FunTest1();//對基類函數進行了重寫,調用派生類的函數
	d.FunTest2();//未對基類函數進行重寫,調用基類函數
	d.FunTest3();
	d.FunTest4();
	Base *pb = &b;
        pb->FunTest1();
	pb = &d;
	pb->FunTest1();

	return 0;
}

以上代碼運行結果如下:

wKiom1cXIWmBQEh2AABApuXl5Yw007.png

由運行結果可知:

 (1).如果在派生類中對基類函數進行了重寫,則在派生類中就調用派生類的成員函數。否則將調用基類的成員函數。

 (2).動態綁定條件:

    a.必須是虛函數

    b.通過基類類型的引用或者指針調用

5.純虛函數

   在成員函數的形參後面寫上=0,則成員函數爲純虛函數。包含純虛函數的類叫做抽象類(也叫接口類),抽象類不能實例化出對象。純虛函數在派生類中重新定義以後,派生類才能實例化出對象。

純虛函數舉例:

class A
{
	virtual void Test() = 0;//純虛函數
};

6.總結:

 (1).派生類重寫基類的虛函數實現多態,要求函數名、參數列表、返回值完全相同。

 (2).基類中定義了虛函數,在派生類中該函數始終保持虛函數的特性。

 (3).只有類的成員函數才能定義爲虛函數,靜態成員函數不能定義爲虛函數。

 (4).如果在類外定義虛函數,只能在聲明函數時加virtual關鍵字,定義時不用加。

 (5).構造函數不能定義爲虛函數

 (6).不要在構造函數和析構函數中調用虛函數,在構造函數和析構函數中,對象是不完整的,可能會出現未定義的行爲。

 (7).虛表是所有類對象實例共用的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章