溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++編譯期多態與運行期多態是什么樣的

發布時間:2021-10-15 09:53:45 來源:億速云 閱讀:161 作者:柒染 欄目:編程語言

C++編譯期多態與運行期多態是什么樣的,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

  今日的C++不再是個單純的“帶類的C”語言,它已經發展成為一個多種次語言所組成的語言集合,其中泛型編程與基于它的STL是C++發展中最為出彩的那部分。在面向對象C++編程中,多態是OO三大特性之一,這種多態稱為運行期多態,也稱為動態多態;在泛型編程中,多態基于template(模板)的具現化與函數的重載解析,這種多態在編譯期進行,因此稱為編譯期多態或靜態多態。

  運行期多態

  運行期多態的設計思想要歸結到類繼承體系的設計上去。對于有相關功能的對象集合,我們總希望能夠抽象出它們共有的功能集合,在基類中將這些功能聲明為虛接口(虛函數),然后由子類繼承基類去重寫這些虛接口,以實現子類特有的具體功能。典

  class Animal

  {

  public :

  virtual void shout() = 0;

  };

  class Dog :public Animal

  {

  public:

  virtual void shout(){ cout << "汪汪!"<   };   class Cat :public Animal   {   public:   virtual void shout(){ cout << "喵喵~"<   };   class Bird : public Animal   {   public:   virtual void shout(){ cout << "嘰喳!"<   };   int main()   {   Animal * anim1 = new Dog;   Animal * anim2 = new Cat;   Animal * anim3 = new Bird;   //藉由指針(或引用)調用的接口,在運行期確定指針(或引用)所指對象的真正類型,調用該類型對應的接口   anim1->shout();

  anim2->shout();

  anim3->shout();

  //delete 對象

  ...

  return 0;

  }

  運行期多態的實現依賴于虛函數機制。當某個類聲明了虛函數時,編譯器將為該類對象安插一個虛函數表指針,并為該類設置一張唯一的虛函數表,虛函數表中存放的是該類虛函數地址。運行期間通過虛函數表指針與虛函數表去確定該類虛函數的真正實現。

  運行期多態的優勢還在于它使處理異質對象集合稱為可能:

  //我們有個動物園,里面有一堆動物

  int main()

  {

  vectoranims;

  Animal * anim1 = new Dog;

  Animal * anim2 = new Cat;

  Animal * anim3 = new Bird;

  Animal * anim4 = new Dog;

  Animal * anim5 = new Cat;

  Animal * anim6 = new Bird;

  //處理異質類集合

  anims.push_back(anim1);

  anims.push_back(anim2);

  anims.push_back(anim3);

  anims.push_back(anim4);

  anims.push_back(anim5);

  anims.push_back(anim6);

  for (auto & i : anims)

  {

  i->shout();

  }

  //delete對象

  //...

  return 0;

  }

  總結:運行期多態通過虛函數發生于運行期

  編譯期多態

  對模板參數而言,多態是通過模板具現化和函數重載解析實現的。以不同的模板參數具現化導致調用不同的函數,這就是所謂的編譯期多態。相比較于運行期多態,實現編譯期多態的類之間并不需要成為一個繼承體系,它們之間可以沒有什么關系,但約束是它們都有相同的隱式接口。我們將上面的例子改寫為:

  class Animal

  {

  public :

  void shout() { cout << "發出動物的叫聲" << endl; };   };   class Dog   {   public:   void shout(){ cout << "汪汪!"<   };   class Cat   {   public:   void shout(){ cout << "喵喵~"<   };   class Bird   {   public:   void shout(){ cout << "嘰喳!"<   };   template   void animalShout(T & t)   {   t.shout();   }   int main()   {   Animal anim;   Dog dog;   Cat cat;   Bird bird;   animalShout(anim);   animalShout(dog);   animalShout(cat);   animalShout(bird);   getchar();   }   在編譯之前,函數模板中t.shout()調用的是哪個接口并不確定。在編譯期間,編譯器推斷出模板參數,因此確定調用的shout是哪個具體類型的接口。不同的推斷結果調用不同的函數,這就是編譯器多態。這類似于重載函數在編譯器進行推導,以確定哪一個函數被調用。   運行期多態與編譯期多態優缺點分析   運行期多態優點

  OO設計中重要的特性,對客觀世界直覺認識。

  能夠處理同一個繼承體系下的異質類集合。

  運行期多態缺點

  運行期間進行虛函數綁定,提高了程序運行開銷。

  龐大的類繼承層次,對接口的修改易影響類繼承層次。

  由于虛函數在運行期在確定,所以編譯器無法對虛函數進行優化。

  虛表指針增大了對象體積,類也多了一張虛函數表,當然,這是理所應當值得付出的資源消耗,列為缺點有點勉強。

  編譯期多態優點

  它帶來了泛型編程的概念,使得C++擁有泛型編程與STL這樣的強大武器。

  在編譯器完成多態,提高運行期效率。

  具有很強的適配性與松耦合性,對于特殊類型可由模板偏特化、全特化來處理。

  編譯期多態缺點

  程序可讀性降低,代碼調試帶來困難。

  無法實現模板的分離編譯,當工程很大時,編譯時間不可小覷。

  無法處理異質對象集合。

  關于顯式接口與隱式接口

  所謂的顯式接口是指類繼承層次中定義的接口或是某個具體類提供的接口,總而言之,我們能夠在源代碼中找到這個接口.顯式接口以函數簽名為中心,例如

  void AnimalShot(Animal & anim)

  {

  anim.shout();

  }

  我們稱shout為一個顯式接口。在運行期多態中的接口皆為顯式接口。

  而對模板參數而言,接口是隱式的,奠基于有效表達式。例如:

  template

  void AnimalShot(T & anim)

  {

  anim.shout();

  }

  對于anim來說,必須支持哪一種接口,要由模板參數執行于anim身上的操作來決定,在上面這個例子中,T必須支持shout()操作,那么shout就是T的一個隱式接口。

關于C++編譯期多態與運行期多態是什么樣的問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女