在上一篇 C++ 學習筆記 (六) 繼承- 子類與父類有同名函數,變量 中說了當父類子類有同名函數時在外部調用時如果不加父類名則會默認調用子類的函數。C++有函數重寫的功能需要添加virtual關鍵字,當時寫上篇博文的時候在想那么既然默認使用子類的同名函數那么這個virtual有什么意義呢?
這篇博文主要講述 多態:一句相同的語句能有不同的實現。
當父類和子類有同名函數,調用時牽扯到了指針那么就跟virtual有關系了。
看以下幾種情況:
定義兩個類:父類子類有同名函數print();
1 class Parent 2 { 3 public: 4 5 void print() //子類的和父類的函數名字一樣 6 { 7 cout<<"Parent 打印 "<<endl; 8 } 9 10 }; 11 12 class Child : public Parent 13 { 14 public: 15 16 void print() 17 { 18 cout<<"Child 打印 "<<endl; 19 } 20 21 };
1.當父類和子類都有同名函數prin()t時,使用Parent 類指針,指向子類對象或者父類對象調用的函數都是父類的函數。
Parent *base = NULL;
5 base = &p1; //父類對象 6 base->print(); //執行父類的打印函數 7 8 base = &c1; //子類對象 9 base->print(); //也是執行父類函數
2.使用引用,當引用是父類時調用的函數也是父類的同名函數
Parent &base2 = p1; base2.print();//調用父類函數 Parent &base3 = c1; //base3是c1 的別名 base3.print(); //調用父類函數
3.函數傳參為父類 類型時,無論傳入子類還是父類都只執行父類的函數
void howToPrint(Parent *base) //傳參為父類的指針
{ base->print(); }
void howToPrint2(Parent &base) //傳參為父類的引用 { base.print(); } //函數調用 均執行父類的函數 howToPrint(&p1); howToPrint(&c1); howToPrint2(p1)
howToPrint2(c1);
總結:
其實上面三個情景下當我們一個指針指向了子類,或者引用子類那么我們希望調用函數的時候是調用子類的函數,但是實際情況卻不是這樣。這時候就需要virtual關鍵字了。
1 lass Parent 2 { 3 public: 4 5 virtual void print() //子類的和父類的函數名字一樣 6 { 7 cout<<"Paren打印 "<<endl; 8 } 9 10 }; 11 12 class Child : public Parent 13 { 14 public: 15 16 virtual void print() //virtual 父類寫了virtual,子類可寫 可不寫 17 { 18 cout<<"Child 打印 "<<endl; 19 } 20 21 };
使用了virtual關鍵字定義的函數,那么在上述三種情況下只要指針是指向子類,或是引用子類那么往后的調用就按照我們的預想調用子類里的函數。再回顧一下這句話:
多態:一句相同的語句能有不同的實現。
舉例:
void howToPrint(Parent *base) //傳參為父類的指針
{ base->print(); } 傳入的指針決定了最后執行的函數,出入父類指針則執行父類的print函數,出入父類的派生類則調用這個派生類的print函數,這樣一句相同的語句就有了不同的實現。
void howToPrint(Parent *base) //傳參為父類的指針