1、封裝及封裝的意義
封裝可以隱藏實現細節,使得**模組化;封裝是把過程和資料報圍起來,對資料的訪問只能通過已定義的介面。物件導向計算始於這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的物件,這些物件通過乙個受保護的介面訪問其他物件。在物件導向程式設計上可理解為:把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行資訊隱藏
下面我們就以polocar這個類開始吧!
class cpolocar ;
到這裡我們建立了乙個叫做polocar 的類,其成員包括靜態和非靜態資料成員,靜態與非靜態函式成員。
靜態資料成員:static char _zxqi[20]靜態類中的成員加入static修飾符,即是靜態成員.可以直接使用類名+靜態成員名訪問此靜態成員,因為靜態成員存在於記憶體,非靜態成員需要例項化才會分配記憶體,所以靜態成員不能訪問非靜態的成員..因為靜態成員存在於記憶體,所以非靜態成員可以直接訪問類中靜態的成員
靜態函式成員:static void fast()所有沒有加static的成員都是非靜態成員,當類被例項化之後,可以通過例項化的類名進行訪問..非靜態成員的生存期決定於該類的生存期..而靜態成員則不存在生存期的概念,因為靜態成員始終駐留在內容中..
3、在面向過程設計中的static關鍵字
1)、靜態全域性變數
定義:在全域性變數前,加上關鍵字 static 該變數就被定義成為了乙個靜態全域性變數。
特點:
a、該變數在全域性資料區分配記憶體。
b、初始化:如果不顯式初始化,那麼將被隱式初始化為0(自動變數是隨機的,除非顯式地初始化)。
c、訪變數只在本原始檔可見,嚴格的講應該為定義之處開始到本檔案結束。
d、檔案作用域下宣告的const的常量預設為static儲存型別。
例(摘於c++程式設計教程---錢能主編p103):
//example 1
#include
void fn();
static
intn;//定義靜態全域性變數
void main()
void fn()
靜態變數都在全域性資料區分配記憶體,包括後面將要提到的靜態區域性變數。對於乙個完整的程式,在記憶體中的分布情況如下圖:
**區全域性資料區
堆區棧區
void main()
//file2
#include
extern
int n;(可在別的檔案中引用這個變數)
void fn()
編譯並執行example 2,您就會發現上述**可以分別通過編譯,但link時出現錯誤。
試著將 static int n; //定義靜態全域性變數
改為 int n; //定義全域性變數
再次編譯執行程式,細心體會全域性變數和靜態全域性變數的區別。
2)、靜態區域性變數
定義:在區域性變數前加上static關鍵字時,就定義了靜態區域性變數。我們先舉乙個靜態區域性變數的例子,
//example 3
#include
void fn();
void main()
void fn()
通常,在函式體內定義了乙個變數,每當程式執行到該語句時都會給該區域性變數分配棧記憶體。但隨著程式退出函式體,系統就會收回棧記憶體,區域性變數也相應失效。
但有時候我們需要在兩次呼叫之間對變數的值進行儲存。通常的想法是定義乙個全域性變數來實現。但這樣一來,變數已經不再屬於函式本身了,不再僅受函式的控制,給程式的維護帶來不便。
靜態區域性變數正好可以解決這個問題。靜態區域性變數儲存在全域性資料區,而不是儲存在棧中,每次的值保持到下一次呼叫,直到下次賦新值。
特點:
a、該變數在全域性資料區分配記憶體。
b、初始化:如果不顯式初始化,那麼將被隱式初始化為0,以後的函式呼叫不再進行初始化。
c、它始終駐留在全域性資料區,直到程式執行結束。但其作用域為區域性作用域,當定義它的函式或 語句塊結束時,其作用域隨 之結束。
3)、靜態函式(注意與類的靜態成員函式區別)
定義:在函式的返回型別前加上static關鍵字,函式即被定義成靜態函式。
特點:
a、靜態函式與普通函式不同,它只能在宣告它的檔案當中可見,不能被其它檔案使用。
定義靜態函式的好處:靜態函式不能被其它檔案所用;
其它檔案中可以定義相同名字的函式,不會發生衝突;
4、物件導向的static關鍵字(類中的static關鍵字)
1)、靜態資料成員
在類內資料成員的宣告前加上關鍵字static,該資料成員就是類內的靜態資料成員。
先舉乙個靜態資料成員的例子。
cpolocar::cpolocar()
cpolocar::~cpolocar()
void
cpolocar::zhuanxiang()
void
cpolocar::brake()
void
cpolocar::giveoil()
void
cpolocar::dealbrake()
void
cpolocar::zxzlqi()
void
cpolocar::n**igation()
void
cpolocar::playmusic()
可以看出,靜態資料成員有以下特點:
靜態資料成員初始化與一般資料成員初始化不同。
靜態資料成員初始化的格式為:
<資料型別><類名>::<靜態資料成員名>=<值>
類的靜態資料成員有兩種訪問形式:
<類物件名>.<靜態資料成員名> 或 <類型別名>::<靜態資料成員名>
對於非靜態資料成員,每個類物件都有自己的拷貝。而靜態資料成員被當作是類的成員。無論這個類的物件被定義了多少個,靜態資料成員在程式中也只有乙份拷貝,由該型別的所有物件共享訪問。也就是說,靜態資料成員是該類的所有物件所共有的。對該類的多個物件來說,靜態資料成員只分配一次記憶體,供所有物件共用。所以,靜態資料成員的值對每個物件都是一樣的,它的值可以更新;
靜態資料成員儲存在全域性資料區。靜態資料成員定義時要分配空間,所以不能在類宣告中定義。在example 5中,語句int myclass::sum=0;是定義靜態資料成員;
靜態資料成員和普通資料成員一樣遵從public,protected,private訪問規則;
因為靜態資料成員在全域性資料區分配記憶體,屬於本類的所有物件共享,所以,它不屬於特定的類物件,在沒有產生類物件時其作用域就可見,即在沒有產生類的例項時,我們就可以操作它;
如果靜態資料成員的訪問許可權允許的話(即public的成員),可在程式中,按上述格式來引用靜態資料成員
; 靜態資料成員主要用在各個物件都有相同的某項屬性的時候。比如對於乙個存款類,每個例項的利息都是相同的。所以,應該把利息設為存款類的靜態資料成員。
這有兩個好處,第一,不管定義多少個存款類物件,利息資料成員都共享分配在全域性資料區的記憶體,所以節省儲存空間。
第二,一旦利息需要改變時,只要改變一次,則所有存款類物件的利息全改變過來了;
同全域性變數相比,使用靜態資料成員有兩個優勢:
靜態資料成員沒有進入程式的全域性名字空間,因此不存在與程式中其它全域性名字衝突的可能性;
可以實現資訊隱藏。靜態資料成員可以是private成員,而全域性變數不能;
2、靜態成員函式
與靜態資料成員一樣,我們也可以建立乙個靜態成員函式,它為類的全部服務而不是為某乙個類的具體物件服務。靜態成員函式與靜態資料成員一樣,都是類的內部實現,屬於類定義的一部分。普通的成員函式一般都隱含了乙個this指標,this指標指向類的物件本身,因為普通成員函式總是具體的屬於某個類的具體物件的。通常情況下,this是預設的。如函式fn()實際上是this->fn()。
但是與普通函式相比,靜態成員函式由於不是與任何的物件相聯絡,因此它不具有this指標。從這個意義上講,它無法訪問屬於類物件的非靜態資料成員,也無法訪問非靜態成員函式,它只能呼叫其餘的靜態成員函式。
下面舉個靜態成員函式的例子。
//example 6
#include
class myclass
;int myclass::sum=0;//定義並初始化靜態資料成員
myclass::myclass(int a,int b,int c)
void myclass::getsum() //靜態成員函式的實現
{
// cout < 靜態成員函式由於不是與任何的物件相聯絡,因此它不具有this指標。從這個意義上講,它無法訪問屬於類物件的非靜態資料成員,也無法訪問非靜態成員函式,它只能呼叫其餘的靜態成員函式。
cout < <"sum=" < 靜態成員之間可以相互訪問,包括靜態成員函式訪問靜態資料成員和訪問靜態成員函式;
非靜態成員函式可以任意地訪問靜態成員函式和靜態資料成員;
靜態成員函式不能訪問非靜態成員函式和非靜態資料成員;
由於沒有this指標的額外開銷,因此靜態成員函式與類的全域性函式相比速度上會有少許的增長;
呼叫靜態成員函式,可以用成員訪問操作符(.)和(->)為乙個類的物件或指向類物件的指標呼叫靜態成員函式.
C 學習 物件導向
封裝 把客觀事物封裝成類,並將類內部的實現隱藏,以保證資料的完整性 比如年齡賦值為負數,就是個例子。當我們把類的字段定義為公共型別時,外部物件可以直接對類內部的資料進行操作,此時無法對這些操作進行一些邏輯判斷!物件導向程式設計中的封裝特性,是一種保護狀態資料完整性的方法。在物件導向程式設計中,應更多...
C 學習筆記(物件導向)
protected 受保護的 用protected宣告的成員稱為受保護的成員,它不能被類外訪問,但是可以被派生類的成員函式訪問 在類體中,既不寫關鍵字private,又不寫public,則預設為private 宣告類的方法是由宣告結構體型別的方法發展來的 在類體中直接定義函式時,不需要在函式名前邊加...
c 學習 委託 物件導向
using system using system.collections.generic using system.linq using system.text using system.threading.tasks namespace project2 static double divide...