天天看點

OOP面向對象程式設計——C++

 OOP程式設計的一些概念:

         一.對象(Object),這個概念可以說是面向對象裡面的最為核心的概念,如果找不着對象,又如何面向對象呢?對象,也就是你要處理的問題裡面設計的若幹個因素,比如你做學生成績統計,那麼學生當然是你要考慮的對象。

        二.類(Class),從本質上講是先有對象才有類,因為在處理的實際程式設計問題時,你面對的是一個個具體的對象,太多了,怎麼辦?分門别類,實作物以類聚,對了,将相同屬性的對象作為一類進行考慮,張三也好,李四也好,他們都是人的一個執行個體。在具體的語言實作時,兩者的順序就需要颠倒一下了,也就是要先有類,然後才能執行個體化生成對象。

       三.面向對象的三大特性:

      3.1 封裝

            所謂的封裝也就是在類的設計時,實作對于類内的資料與方法的不同權限設定,有些資料和方法,我們不希望使用者在類的外部通過執行個體化去調用,那麼我們将它們聲明成私有的(private),這樣這些資料和方法隻能被類内部的成員函數通路,而如果希望能夠被執行個體通路,那麼聲明成公有的(public),至于第三種通路區分符(protected)保護型的,在類的繼承時應用,我們到繼承那裡說明。

       與封裝有關的一個概念是“抽象”(abstract) ,即将設計的類的最主要的功能表示出來,這些功能正是要被其他類和函數通路的。

      3.2 繼承

       與繼承有關的概念是關系,關系描述了類之間的聯系,有四種基本類型,即“繼承、組合、利用、執行個體化”。繼承就是說某一個類具有了另外一個類所有的資料和方法,當然可以修改一部分并且增加新的資料和方法。繼承分為兩種類型,即單重繼承和多重繼承。

        單重繼承,即類Derived繼承了類Base,定義如下:

         class Base

        {

        };

       class Derived:public Base

         {

        }

       可見在定義繼承類時,要指明繼承了哪一個類,并且指明繼承級别(public,protected,private),通過這三種通路區分符的修飾,可以改變基類資料在派生類中的通路權限,public 繼承不會改變,protected繼承的話原來的public 資料和方法變成派生類的protected型資料和方法,其他不變,private繼承則将所有的資料和方法的通路權限設定為private,即這些資料和方法都不能在類的外部通路。

        派生類的構造和析構順序,首先構造基類,然後構造派生類,中間是類的作用,析構順序正好相反。

      多重繼承是說一個類繼承了兩個或者多個類的資料或者方法。在多重繼承這裡預見的主要的問題是兩個歧義性:首先,當繼承的兩個基類中含有相同的資料或者方法時,在派生類中調用無法區分,解決方法:指明調用的哪一個類的成員變量和方法,使用作用域分解運算符;在派生類裡面重新定義該資料或者方法。第二類歧義性發生在多層繼承時,B,C繼承了A,而D又繼承了B,C,正如矩形和菱形繼承四邊形而正方形繼承了矩形和菱形,兩條繼承路徑使得基類被兩次繼承,直接通路無法區分,解決方法:支出繼承路徑,使用虛基類(virtual)方法,在定義繼承關系時添加virtual使得基類永遠隻有一份拷貝。

      3.3 多态

      多态性分為兩種,即靜态多态性和動态多态性。所謂多态,也就是明明同樣一個東西,在不同情況下有着不同的表現。

       靜态多态性,即預先定義好的,通過函數重載(funcition overload)實作,函數包含了傳回值、函數名稱、函數參數三個,名字多表示功能,傳回值的區分不能區分函數(想象資料類的強制轉換吧)。是以重載也就是函數名稱相同而參數不同,不同可以表現在參數個數不同、參數類型不同、參數順序不同。

      例如 int max(int,int)

                float max(float,float)

     另外我們自己定義了希望在這個新的類型上仍然能夠實作我們原有的算術運算、邏輯運算等運算符,解決機制是運算符重載,即我們可以将系統原有的運算符(不是全部)重新定義在我們自己的類上實作。如

    Complex  Complex::operator + (const Complex  & C1)

  在複數類上定義了自己的加法運算。

        動态多态性呢,是說在程式執行的時候有着不同的表現。涉及的一個概念是“聯編”,也就是我們要用某一個類的方法,一般情況下總是通過這個類的執行個體或者指針,這是系統必須知道這個函數是哪一個類的,即由對象到類的過程,有些聯編在編譯時就可以,但是有些隻能在程式實際執行時确定,也就是 滞後聯編。為了實作滞後聯編,我們需要将基類的函數設定為虛函數(virtual),這樣實作滞後聯編。

        如類Manager 和 Saler 都繼承了類Employee,三個類都有方法CalcSalary(),程式如下:

         Employee * ptr;

        ptr = new Manager;

         ptr->CalcSalary();

        ptr = new Saler;

        ptr->CalcSalary().

      我們希望的正是兩個函數有着不同的輸出,虛函數實作了這一點。

        純虛函數,virtual CalcSalary()=0;函數沒有實體,就等着在派生類裡面重新設計了,包含了一個或者多個純虛函數的類是抽象類,抽象類不能執行個體化但是可以被指針指向。

四。構造函數與析構函數

        構造函數和析構函數是類中特殊的兩個函數。構造函數負責對類内部的資料進行初始化,構造函數沒有傳回值,名稱與類相同,可以重載。析構函數實作去初始化,在類結束前進行掃尾工作,沒有傳回值類型,名稱與類相同,但是前面加~以表示否定,不能重載,不需要調用。

五.Const關鍵字 以及Volatile 關鍵字

     作用有二:定義常量變量類型 const double PI = 3.1415926;

                         修飾參數,一般用于修飾輸入參數,使得其隻能讀不能寫。

     另外比較重要的:還有就是防止指針被修改

     提到Const就不能不說到Volatile關鍵字,兩者構成了c-v qualifier(所謂的c-v限定)

     話說此關鍵字乃吾心中之痛:曾被一個牛人面到不知其意~~  捶地啊!

     回來後就查詢,學習……籠統的說是告訴編譯器“不知何時會改變”

     換言之,就是聲明的東西可以由外部程式改變,禁止編譯器對讀寫操作進行任何優化。

     如此确定的表達一個不确定的資訊,實屬罕見!  but, 這個不是我不知道此用法的借口,看來還需修煉

六。static關鍵字

          定義靜态函數和靜态資料,靜态資料表所有這個類的對象共同維護一個資料,相當于這個類的全局變量,隻能通過類通路,初始化為0。靜态函數實作了不定義對象通路類的功能,靜态函數隻能通路靜态資料。

七.inline關鍵字

         内聯函數,實作對于簡短函數的替換操作,提高速度。

      這個關鍵字其實内涵也很深,與C中的define有相似的作用,但差别也很多,不僅僅是簡單的替換功效

      記得和某位牛人探讨此函數的功效,用法時,收獲頗深……