談談自己對面向對象的理解


三個特征

封裝

把客觀事物封裝成抽象的類,並且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。

繼承

繼承是指這樣一種能力:它可以使用現有類的所有功能,並在無需重新編寫原來的類的情況下對這些功能進行擴展。其繼承的過程,就是從一般到特殊的過程。

組合

如果鳥是可以飛的,那么鴕鳥是鳥么?鴕鳥如何繼承鳥類?[美國某著名分析軟件公司2005年面試題]
解析:如果所有鳥都能飛,那鴕鳥就不是鳥!回答這種問題時,不要相信自己的直覺!將直覺和合適的繼承聯系起來還需要一段時間。
根據題干可以得知:鳥是可以飛的。也就是說,當鳥飛行時,它的高度是大於0的。鴕鳥是鳥類(生物學上)的一種。但它的飛行高度為0(鴕鳥不能飛)。
不要把可替代性和子集相混淆。即使鴕鳥集是鳥集的一個子集(每個駝鳥集都在鳥集內),但並不意味着鴕鳥的行為能夠代替鳥的行為。可替代性與行為有關,與子集沒有關系。當評價一個潛在的繼承關系時,重要的因素是可替代的行為,而不是子集。
答案:如果一定要讓鴕鳥來繼承鳥類,可以采取組合的辦法,把鳥類中的可以被鴕鳥繼承的函數挑選出來,這樣鴕鳥就不是“a kind of”鳥了,而是“has some kind of”鳥的屬性而已。代碼如下:

 1 #include<string>
 2 #include<iostream>
 3 using namespace std;
 4 class bird
 5 {
 6 public:
 7     void eat()
 8     {
 9         cout << "bird is eating" << endl;
10     }
11     void sleep()
12     {
13         cout << "bird is sleeping" << endl;
14     }
15     void fly();
16 };
17 
18 class ostrich
19 {
20 public:
21     eat()
22     {
23         smallBird.eat();
24     }
25     sleep()
26     {
27         smallBird.sleep();
28     }
29 private:
30     bird smallBird;
31 
32 };
33 
34 int main()
35 {
36     ostrich xiaoq;
37     xiaoq.eat();
38     xiaoq.sleep();
39     return 0;
40 }
View Code

多態

多態性指相同對象收到不同消息或不同對象收到相同消息時產生不同的實現動作。C++支持兩種多態性:編譯時多態性,運行時多態性。

a.編譯時多態性:通過重載實現  靜態  早綁定(編譯時綁定)
b 運行時多態性:通過覆蓋實現  動態  晚綁定(運行時綁定)

注意如果說面向對象的多態不包括重載:重載編譯時就確定了,是靜態,是一種語言特性,與面向對象也無關!引用一句Bruce Eckel的話:“不要犯傻,如果它不是晚邦定,它就不是多態。”

overide(覆蓋)和overload(重載)

a.成員函數被重載的特征:
(1)相同的范圍(在同一個類中)
(2)函數名字相同
(3)參數不同
(4)virtual 關鍵字可有可無
b.覆蓋是指派生類函數覆蓋基類函數,特征是:
(1)不同的范圍(分別位於派生類與基類)
(2)函數名字相同
(3)參數相同
(4)基類函數必須有virtual 關鍵字

C++對象模型告訴你如何實現多態,有兩個概念可以解釋C++對象模型:

語言中直接支持面向對象程序設計的部分。
對於各種支持的底層實現機制。

多態是通過重載(虛函數)實現的,下一篇講C++對象模型

 

動態綁定例子

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class Base
 5 {
 6 public:
 7     void fun1(){ cout << "Base fun1" << endl; }
 8     virtual void fun2(){ cout << "Base fun2" << endl; }
 9 private:
10     int a;
11 };
12 
13 class Derive :  public Base
14 {
15 public:
16     void fun1(){ cout << "Derive fun1" << endl; }
17     void fun2(){ cout << "Derive fun2" << endl; }
18     virtual void fun3(){}
19 private:
20     int b;
21 };
22 
23 int main()
24 {
25     Base b;
26     Derive d;
27     Base *p = &d;
28     p->fun1();
29     p->fun2();
30 
31     system("pause");
32     return 0;
33 }

 

輸出:基類指針p在運行時發生動態綁定,fun2調用子類方法,fun1由於沒有virtual,仍然調用父類方法 

 

內存模型:

指針的虛表指向子類方法地址

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM