關於多態的小結

  1. 什麼是多態?
    編程

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

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

    wKiom1cXA6ShkMMEAAA7M48LKTc565.png

  3. 靜態多態:spa

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

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. 動態多態:對象

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

  使用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;
}

以上代碼運行結果以下:ci

wKiom1cXIWmBQEh2AABApuXl5Yw007.png

由運行結果可知:

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

 (2).動態綁定條件:

    a.必須是虛函數

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

5.純虛函數

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

純虛函數舉例:

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

6.總結:

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

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

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

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

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

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

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

相關文章
相關標籤/搜索