淺析c++面向對象特性
2018-08-15 20:17:14
1、三大特性
所謂封裝,也就是把客觀事物封裝成抽象的類,並且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。封裝是面向對象的特征之一,是對象和類概念的主要特性。 簡單的說,一個類就是一個封裝了數據以及操作這些數據的代碼的邏輯實體。在一個對象內部,某些代碼或某些數據可以是私有的,不能被外界訪問。通過這種方式,對象對內部數據提供了不同級別的保護,以防止程序中無關的部分意外的改變或錯誤的使用了對象的私有部分。
class Student { public: Student(string _name):name(_name){}void hello(); protected(or private): string name; };
上面實現了一個簡單的類,其中有公共的一些接口,即public修飾的hello函數,以及由protected或者private修飾的類成員變量,它們是只可以由類內的成員函數訪問,盡管由外部實現了的類也不能直接通過成員操作符或者指針訪問和修改。這裏可以保證類裏
的數據可以得到充分的保護。
所謂繼承是指可以讓某個類型的對象獲得另一個類型的對象的屬性的方法。它支持按級分類的概念。繼承是指這樣一種能力:它可以使用現有類的所有功能,並在無需重新編寫原來的類的情況下對這些功能進行擴展。 通過繼承創建的新類稱為“子類”或“派生類”,被繼承的類稱為“基類”、“父類”或“超類”。繼承的過程,就是從一般到特殊的過程。要實現繼承,可以通過“繼承”(Inheritance)和“組合”(Composition)來實現。繼承概念的實現方式有二類:實現繼承與接口繼承。實現繼承是指直接使用基類的屬性和方法而無需額外編碼的能力;接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力;
繼承方式 | public | protected | private |
父類中的public | public | protected | private |
父類中的protected | protected | protected | private |
父類中的private | private | private | private |
不同的繼承方式使得父類在子類中的訪問權限不同,既是對父類的保護,也能提高代碼復用,減輕程序的工作量。
所謂多態就是指一個類實例的相同方法在不同情形有不同表現形式。多態機制使具有不同內部結構的對象可以共享相同的外部接口。這意味著,雖然針對不同對象的具體操作不同,但通過一個公共的類,它們(那些操作)可以通過相同的方式予以調用。
這裏首先要介紹一下多態裏用到的virtual修飾符,由於在繼承的過程中,父類的所有成員都被繼承到了子類當中,因此操作系統在分配的內存的時候會重復地給父類的成員變量分配內存空間,並且在實例化子類的時候父類的構造函數和析構函數也將多次調用,導致了內存的浪費,通過在繼承的時候加入virtual聲明繼承方式,能夠只在內存保留一份父類的副本。說到這裏,回到多態,也是相似的原理:通過將父類的成員函數聲明為virtual,從而在多個子類繼承的時候,能夠通過動態聯接找到應該指向的子類方法。
引用:在C++中通過虛函數表的方式實現多態,每個包含虛函數的類都具有一個虛函數表(virtual table),在這個類對象的地址空間的最靠前的位置存有指向虛函數表的指針。在虛函數表中,按照聲明順序依次排列所有的虛函數。實例化一個對象時調用完構造函數後,便會初始化這些指針。由於C++在運行時並不維護類型信息,所以在編譯時直接在子類的虛函數表中將被子類重寫的方法替換掉。當程序中將要調用一個虛函數時,編譯器會編譯成從指針中找到具體的實現函數。因為虛函數指針在對象實例化時就被初始化了,所以即便是該對象被一個父類指針指向也能找到正確的函數。
另外,一日為虛終生為虛。一個函數被聲明為虛時,其衍生類的該函數也將一直是虛函數,即使衍生類沒有顯式聲明為virtual。
class Base_class { public: Base_class(string _name):name(_name) { cout<<"this is constructor"<<endl; } // ~Base_class() // { // cout<<"this is destructor"<<endl; // } virtual void say_hi(int) const =0; protected: string name; }; class sub_class:public Base_class { public: sub_class(string _name,int _sex):sex(_sex),Base_class(_name){} void say_hi(int) const; private: int sex; }; class sub_class_:public Base_class { public: sub_class_(string _name,int _score):score(_score),Base_class(_name){} void say_hi(int ) const; private: int score; }; void sub_class::say_hi(int num) const { cout<<"sex:"<<sex<<endl; } void sub_class_::say_hi(int num) const { cout<<"score: "<<score<<endl; } int main() { Base_class *s = new sub_class("wang",1); Base_class *s1 = new sub_class_("Li",2); s->say_hi(2); s1->say_hi(3); delete s; delete s1; return 0; }
上述是兩個子類對父類純虛函數的重寫,註意到主函數裏兩個指針的類型均為基類類型,此時訪問say_hi方法是能夠正確找到子類重寫的方法的,當然,有人問為什麽不直接用子類定義呢,這裏只是兩個指針,使用new產生對象,如果存在了大量的實例化的情況,是可以通過同一指針不同的指向來節省程序員命名變量的數量。
總結:以上是目前學習完《c++程序設計》這本書的基礎認識,之後有新的體會也會繼續增加內容。如有錯誤,還望斧正!
淺析c++面向對象特性