【C++】由Polocar 學習 C++物件導向
1、封裝及封裝的意義
封裝可以隱藏實現細節,使得程式碼模組化;封裝是把過程和資料包圍起來,對資料的訪問只能通過已定義的介面。物件導向計算始於這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的物件,這些物件通過一個受保護的介面訪問其他物件。在物件導向程式設計上可理解為:把客觀事物封裝成抽象的類,並且類可以把自己的資料和方法只讓可信的類或者物件操作,對不可信的進行資訊隱藏
下面我們就以Polocar這個類開始吧!
class CPoloCar {
public:
//C++建構函式,預設的建構函式
CPoloCar();
//解構函式
~CPoloCar();
//靜態音樂屬性
static char Music[20];
//靜態顏色
static char color[10];
//車名
char carName[5];
//方向盤
char _fxPan[20];
//剎車板
char _brakeBan[20];
//油門板
char _oilBan[20];
//轉向
void zhuanXiang();
//剎車
void brake();
//給油
void giveOil();
//導航
static void navigation();
//音樂播放
static void playMusic();
private:
//轉向器
static char _zxqi[20];
//制動器
char _zdqi[20];
//轉向助力器
void zxZlqi();
//制動執行器
void dealBrake();
static void fast();
};
2、類 及 類的成員
到這裡我們建立了一個叫做Polocar 的類,其成員包括靜態和非靜態資料成員,靜態與非靜態函式成員。
靜態資料成員:static char _zxqi[20]
靜態類中的成員加入static修飾符,即是靜態成員.可以直接使用類名+靜態成員名訪問此靜態成員,因為靜態成員存在於記憶體,非靜態成員需要例項化才會分配記憶體,所以靜態成員不能訪問非靜態的成員..因為靜態成員存在於記憶體,所以非靜態成員可以直接訪問類中靜態的成員
靜態函式成員:static void fast()
所有沒有加Static的成員都是非靜態成員,當類被例項化之後,可以通過例項化的類名進行訪問..非靜態成員的生存期決定於該類的生存期..而靜態成員則不存在生存期的概念,因為靜態成員始終駐留在內容中..
定義:在全域性變數前,加上關鍵字 static 該變數就被定義成為了一個靜態全域性變數。
特點:
A、該變數在全域性資料區分配記憶體。
B、初始化:如果不顯式初始化,那麼將被隱式初始化為0(自動變數是隨機的,除非顯式地初始化)。
C、訪變數只在本原始檔可見,嚴格的講應該為定義之處開始到本檔案結束。
例(摘於C++程式設計教程---錢能主編P103): //file1.cpp
//Example 1
#include <iostream.h>
void fn();
static int n;//定義靜態全域性變數
void main()
{
n=20;
cout < <n < <endl;
fn();
}
void fn()
{
n++;
cout < <n < <endl;
}
程式碼區 |
全域性資料區 |
堆區 |
棧區 |
void main()
{
n=20;
cout < <n < <endl;
fn();
}
//File2
#include <iostream.h>
extern int n;(可在別的檔案中引用這個變數)
void fn()
{
n++;
cout < <n < <endl;
}
改為
int n; //定義全域性變數
再次編譯執行程式,細心體會全域性變數和靜態全域性變數的區別。
//Example 3
#include <iostream.h>
void fn();
void main()
{
fn();
fn();
fn();
}
void fn()
{
static n=10;
cout < <n < <endl;
n++;
}
通常,在函式體內定義了一個變數,每當程式執行到該語句時都會給該區域性變數分配棧記憶體。但隨著程式退出函式體,系統就會收回棧記憶體,區域性變數也相應失效。但有時候我們需要在兩次呼叫之間對變數的值進行儲存。通常的想法是定義一個全域性變數來實現。但這樣一來,變數已經不再屬於函式本身了,不再僅受函式的控制,給程式的維護帶來不便。
靜態區域性變數正好可以解決這個問題。靜態區域性變數儲存在全域性資料區,而不是儲存在棧中,每次的值保持到下一次呼叫,直到下次賦新值。
特點:
A、該變數在全域性資料區分配記憶體。
B、初始化:如果不顯式初始化,那麼將被隱式初始化為0,以後的函式呼叫不再進行初始化。
C、它始終駐留在全域性資料區,直到程式執行結束。但其作用域為區域性作用域,當定義它的函式或 語句塊結束時,其作用域隨 之結束。
4、物件導向的static關鍵字(類中的static關鍵字)
1)、靜態資料成員
在類內資料成員的宣告前加上關鍵字static,該資料成員就是類內的靜態資料成員。
CPoloCar::CPoloCar()
{
cout << "方向盤初始化"<< endl;
strcpy(_fxPan,"方向盤初始化");
}
CPoloCar::~CPoloCar()
{
cout << "銷燬這輛車"<< endl;
}
void CPoloCar::zhuanXiang()
{
cout << "轉向" << endl;
}
void CPoloCar::brake()
{
cout << "制動"<<endl;
dealBrake();
}
void CPoloCar::giveOil()
{
cout <<"給油"<<endl;
}
void CPoloCar::dealBrake()
{
cout << "真正執行制動的裝置" <<endl;
}
void CPoloCar::zxZlqi()
{
cout << "實現轉向" << endl;
}
void CPoloCar::navigation()
{
cout << "Navigation"<< endl ;
}
void CPoloCar::playMusic(){
cout<< "Playing music " << Music[20]<<endl ;
}
<資料型別><類名>::<靜態資料成員名>=<值>
<類物件名>.<靜態資料成員名> 或 <類型別名>::<靜態資料成員名>
對於非靜態資料成員,每個類物件都有自己的拷貝。而靜態資料成員被當作是類的成員。無論這個類的物件被定義了多少個,靜態資料成員在程式中也只有一份拷貝,由該型別的所有物件共享訪問。也就是說,靜態資料成員是該類的所有物件所共有的。對該類的多個物件來說,靜態資料成員只分配一次記憶體,供所有物件共用。所以,靜態資料成員的值對每個物件都是一樣的,它的值可以更新;
靜態資料成員儲存在全域性資料區。靜態資料成員定義時要分配空間,所以不能在類宣告中定義。在Example 5中,語句int Myclass::Sum=0;是定義靜態資料成員;
靜態資料成員和普通資料成員一樣遵從public,protected,private訪問規則;
因為靜態資料成員在全域性資料區分配記憶體,屬於本類的所有物件共享,所以,它不屬於特定的類物件,在沒有產生類物件時其作用域就可見,即在沒有產生類的例項時,我們就可以操作它;
靜態資料成員主要用在各個物件都有相同的某項屬性的時候。比如對於一個存款類,每個例項的利息都是相同的。所以,應該把利息設為存款類的靜態資料成員。
同全域性變數相比,使用靜態資料成員有兩個優勢:
靜態資料成員沒有進入程式的全域性名字空間,因此不存在與程式中其它全域性名字衝突的可能性;
可以實現資訊隱藏。靜態資料成員可以是private成員,而全域性變數不能;
2、靜態成員函式
與靜態資料成員一樣,我們也可以建立一個靜態成員函式,它為類的全部服務而不是為某一個類的具體物件服務。靜態成員函式與靜態資料成員一樣,都是類的內部實現,屬於類定義的一部分。普通的成員函式一般都隱含了一個this指標,this指標指向類的物件本身,因為普通成員函式總是具體的屬於某個類的具體物件的。通常情況下,this是預設的。如函式fn()實際上是this->fn()。
//Example 6
#include <iostream.h>
class Myclass
{
public:
Myclass(int a,int b,int c);
static void GetSum();/宣告靜態成員函式
private:
int a,b,c;
static int Sum;//宣告靜態資料成員
};
int Myclass::Sum=0;//定義並初始化靜態資料成員
Myclass::Myclass(int a,int b,int c)
{
this->a=a;
this->b=b;
this->c=c;
Sum+=a+b+c; //非靜態成員函式可以訪問靜態資料成員
}
void Myclass::GetSum() //靜態成員函式的實現
{
// cout < <a < <endl; //錯誤程式碼,a是非靜態資料成員 靜態成員函式由於不是與任何的物件相聯絡,因此它不具有this指標。從這個意義上講,它無法訪問屬於類物件的非靜態資料成員,也無法訪問非靜態成員函式,它只能呼叫其餘的靜態成員函式。
cout < <"Sum=" < <Sum < <endl;
}
void main()
{
Myclass M(1,2,3);
M.GetSum();
Myclass N(4,5,6);
N.GetSum();
Myclass::GetSum();
}
關於靜態成員函式,可以總結為以下幾點:
出現在類體外的函式定義不能指定關鍵字static;
靜態成員之間可以相互訪問,包括靜態成員函式訪問靜態資料成員和訪問靜態成員函式;
非靜態成員函式可以任意地訪問靜態成員函式和靜態資料成員;
靜態成員函式不能訪問非靜態成員函式和非靜態資料成員;
由於沒有this指標的額外開銷,因此靜態成員函式與類的全域性函式相比速度上會有少許的增長;
呼叫靜態成員函式,可以用成員訪問操作符(.)和(->)為一個類的物件或指向類物件的指標呼叫靜態成員函式.
相關文章
- C++ 物件導向 一C++物件
- C++ 類(物件導向初探)C++物件
- 學習筆記:物件導向程式設計技術(C++版)筆記物件程式設計C++
- 物件導向程式設計C++物件程式設計C++
- C++物件導向三大特性C++物件
- C++ 物件導向高階設計C++物件
- C++與物件導向程式設計C++物件程式設計
- Effective C++:物件導向與繼承C++物件繼承
- C++物件導向五子棋C++物件
- C++模組2:物件導向程式設計C++物件程式設計
- C/C++知識要點總結之C++物件導向C++物件
- 學習Rust 物件導向Rust物件
- C++物件導向程式設計_Part1C++物件程式設計
- 物件導向程式設計(C++篇4)——RAII物件程式設計C++AI
- C++程式設計雜談:物件導向 (轉)C++程式設計物件
- 物件導向-由淺入深物件
- PHP學習4——物件導向PHP物件
- Lua學習(二)物件導向物件
- JavaScript學習2:物件導向JavaScript物件
- 侯捷C++物件導向高階開發筆記C++物件筆記
- 物件導向程式設計(C++篇3)——析構物件程式設計C++
- 物件導向程式設計(C++篇2)——構造物件程式設計C++
- Scala學習 2 Scala物件導向物件
- C++ 遞迴與物件導向程式設計基礎C++遞迴物件程式設計
- java學習——物件導向之繼承Java物件繼承
- Lua學習筆記--物件導向(三)筆記物件
- C++ 物件導向的三大特性和五個原則C++物件
- 理解C++物件導向程式設計[多型性部分] (轉)C++物件程式設計多型
- C++物件導向-類和物件那些你不知道的細節原理C++物件
- C++物件導向程式設計(一):基於物件(無成員指標)C++物件程式設計指標
- C++物件導向程式設計 類和物件提高篇 建構函式C++物件程式設計函式
- Flutter學習筆記(8)--Dart物件導向Flutter筆記Dart物件
- js高階 物件導向 學習筆記JS物件筆記
- Java SE 學習---物件導向程式設計Java物件程式設計
- Javascript 物件導向學習1 Function function ObjectJavaScript物件FunctionObject
- Ext學習筆記2-物件導向筆記物件
- C++物件導向程式設計——遞迴實現字串的反序C++物件程式設計遞迴字串
- C++——談談你對物件導向程式設計的認識C++物件程式設計