C++多態

C++多態

多態是C++三大特性之一。 
簡單來說多態就像是“一個接口,多種形態”。多態根據函數地址綁定的先後次序可以分爲靜態多態和動態多態

靜態多態:函數的調用是在編譯期間完成的(靜態綁定。函數重載)。 
動態多態:函數的調用時在程序運行期間完成的(動態綁定。函數重寫)

要實現動態綁定,要有兩個條件。

1、必須是虛函數。 
2、通過基類類型的指針或引用調用虛函數。

先來看看什麼是虛函數:用關鍵字virtual修飾的函數叫虛函數(有的函數不能定義爲虛函數)。

剛在動態多態裏說動態綁定實際上就是函數重寫。 
重寫規則:一定是虛函數,並且一個在基類中,另一個在派生類中。重寫要保證函數的原型(返回值、函數名、參數列表)一致(協變除外,協變是基類返回的是基類的引用或指針,而在派生類中返回的是派生類的指針或引用)。

1.class Base
2.{
3.public:
4. virtual void Funtest()
5. {}
6.};
7.
8.class Derived: public Base
9.{
10.public:
11. virtual void Funtest()
12.};

這個就是簡單的函數重寫。剛剛提到不是所有的函數都可以進行重寫,在這裏提一下。構造函數、拷貝構造、靜態函數、友元函數都不可以重寫(即定義爲虛函數)。析構函數和賦值運算符重載可以重寫(但最好不要將賦值運算符重載設爲虛函數。而最好將基類的析構函數設爲虛函數); 
有一類虛函數叫純虛函數,純虛函數是在虛函數的形參後面寫上=0,那麼這個函數就定義爲了純虛函數,把包含純虛函數的類叫做抽象類。簡單來說就是抽象類也不知道自己要執行具體的什麼功能。而抽象類不能夠實例化一個對象,只有這個抽象類被繼承下去時,派生類才能實例化出對象

1.class A
2.{
3.public:
4. virtual void Funtest() = 0
5. {
6. cout<<"Funtest()"<<endl;
7. }
8.};
9.
10.class B:public A
11.{
12.public:
13. virtual void Funtest()
14.
{
15. cout<<"B::Funtest()"<<endl;
16. }
17.};
18.
19.int main ()
20.
{
21. A a;
22. B b;
23. return 0;
24.}

這裏在A中定義了一個純虛函數Funtest(),然後通過B類繼承下來,在main裏用A和B分別實例化一個對象。

 
在編譯期間報錯,提示抽象的類不能實例化出對象。

現在來詳細看一下具體多態實現中都有什麼類型

1.class Base
2.{
3.public:
4. virtual void Display()//基類是虛函數,派生類繼承下來也是虛函數
5.
{
6. cout<<"Base::Display()"<<endl;
7. }
8.
9. virtual void Display()//基類是虛函數,派生類繼承不是虛函數
10.
{
11. cout<<"Base::Display()"<<endl;
12. }
13.
14. virtual void Display(int a)//基類虛函數是一個有int類型的參數,派生類虛函數有一個char類型的參數
15.
{
16. cout<<"Base::Display(int a)"<<endl;
17. }
18.
19. void Display()//基類不是虛函數,派生類是虛函數
20.
{
21. cout<<"Base::Display()"<<endl;
22. }
23.
24. void Display()//基類不是虛函數,派生類也不是虛函數
25.
{
26. cout<<"Base::Display()"<<endl;
27. }
28.
29. virtual char Display()//基類是一個返回類型爲char類型的虛函數,派生類的返回類型是int型的
30.
{
31. cout<<"Base::Display()"<<endl;
32. return 1;
33. }
34.
35. virtual Base& Display()//基類返回類型爲Base&的,派生類返回值爲Derive&的
36.
{
37. cout<<"Base::Display()"<<endl;
38. return *this;
39. }
40.
41.};
42.
43.class Derived: public Base
44.{
45.public:
46. virtual void Display()
47.
{
48. cout<<"Derived::Display()"<<endl;
49. }
50.
51. void Display()
52.
{
53. cout<<"Derived::Display()"<<endl;
54. }
55.
56. virtual void Display(char a)
57.
{
58. cout<<"Derived::Display(char a)"<<endl;
59. }
60.
61. virtual void Display()
62.
{
63. cout<<"Derived::Display()"<<endl;
64. }
65.
66. void Display()
67.
{
68. cout<<"Derived::Display()"<<endl;
69. }
70.
71. virtual int Display()
72.
{
73. cout<<"Display()"<<endl;
74. return 1;
75. }
76.
77. virtual Derived& Display()
78.
{
79. cout<<"Derived::Display()"<<endl;
80. return *this;
81. }
82.};
83.
84.void test(Base& b)
85.
{
86. b.Display();
87.}
88.
89.
90.int main()
91.
{
92. Base b;
93. Derived d;
94. test(b);
95. test(d);
96. system("pause");
97. return 0;
98.}

先具體的看一下哪種能夠實現多態,哪種不能實現多態。 
1、基類是虛函數,派生類繼承下來也是虛函數

 
這種可以實現多態

2、基類是虛函數,派生類繼承不是虛函數

 
這種也可以實現多態

3、基類虛函數是一個有int類型的參數,派生類虛函數有一個char類型的參數

 
這種不構成多態,不滿足重寫規則

4、基類不是虛函數,派生類是虛函數

 
這種不可以實現多態(基類不必須是虛函數)

5、基類不是虛函數,派生類也不是虛函數

 
這種也不可以實現多態(和上面原因一樣)

6、基類是一個返回類型爲char類型的虛函數,派生類的返回類型是int型的

 
這種系統會報錯,提示既不相同也不協變

7、基類返回類型爲Base&的,派生類返回值爲Derive&的

 
這種可以實現多態(返回值類型分別爲基類和派生類的引用或指針,叫做協變)

主要看一下最後兩種,當返回值類型不一樣時,若返回的是對應類的指針或引用時會協變的,協變是可以實現多態的。否則就既不相同也不協變。

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