C++簡明圖解分析靜態(tài)成員與單例設計模式
靜態(tài)成員概述
1、靜態(tài)成員包括靜態(tài)成員數(shù)據(jù)、靜態(tài)成員函數(shù)
2、成員數(shù)據(jù)、成員函數(shù)被 static修飾 就叫靜態(tài)成員數(shù)據(jù)、靜態(tài)成員函數(shù)
3、不管這個類創(chuàng)建了多少個對象,靜態(tài)成員只有一份,這一份被所有屬于這個類的對象共享。
4、靜態(tài)成員 是屬于類 而不是具體的某個對象。
5、靜態(tài)成員 是在定義完類的時候 就存在了。
靜態(tài)成員數(shù)據(jù)
靜態(tài)變量,是在編譯階段就分配空間,對象還沒有創(chuàng)建時,就已經分配空間。
靜態(tài)成員變量必須在類中聲明,在類外定義。
靜態(tài)數(shù)據(jù)成員不屬于某個對象,在為對象分配空間中不包括靜態(tài)成員所占空間。
class Data { public: int num;//普通成員變量 static int data;//靜態(tài)成員變量(類內聲明) }; //定義的時候 不需要加static int Data::data=100;//類外定義+初始化 void test01() { //data是靜態(tài)成員變量 是屬于類 可以通過類名稱::直接訪問 cout<<Data::data<<endl;//100 //賦值 Data::data = 200; cout<<Data::data<<endl;//200 //data靜態(tài)變量 是所有對象 共享的 可以通過對象名訪問 Data ob1; ob1.data = 300; cout<<Data::data<<endl;//300 Data ob2; cout<<ob2.data<<endl;//300 //普通成員變量 屬于對象的 只能通過對象名訪問 ob1.num = 100; cout<<"ob2.num = "<<ob2.num<<endl;//隨機值 //cout<<Data::num<<endl;//普通成員變量不能通過類名稱訪問 }
static修飾靜態(tài)成員函數(shù)
靜態(tài)成員函數(shù):只能訪問私有靜態(tài)數(shù)據(jù)
引出:
class Data { private: int num;//普通成員變量 static int data;//靜態(tài)成員變量(類內聲明) public: //普通成員函數(shù) 依賴于 對象的 必須對象調用 int getData(void) { return data; } }; //定義的時候 不需要加static int Data::data=100;//類外定義+初始化 void test01() { //cout<<Data::data<<endl;//err 靜態(tài)data是私有的 類外不能直接訪問 //cout<< Data::getData()<<endl;//err getData() 必須對象調用 Data ob; cout<<ob.getData()<<endl; //存在問題:data靜態(tài)的 在創(chuàng)建對象之前 就已經存在 //如果類沒有實例化對象 難道 就不能使用data了嗎? //解決上述問題 就要用到靜態(tài)成員函數(shù) }
靜態(tài)成員函數(shù):
class Data { private: int num;//普通成員變量 static int data;//靜態(tài)成員變量(類內聲明) public: //普通成員函數(shù) 依賴于 對象的 必須對象調用 int getData(void) { return data; } //靜態(tài)成員函數(shù) 屬于類 而不屬于對象 static int getDataStatic(void) { return data; } }; //定義的時候 不需要加static int Data::data=100;//類外定義+初始化 void test01() { //cout<<Data::data<<endl;//err 靜態(tài)data是私有的 類外不能直接訪問 //cout<< Data::getData()<<endl;//err getData() 必須對象調用 Data ob; cout<<ob.getData()<<endl; //存在問題:data靜態(tài)的 在創(chuàng)建對象之前 就已經存在 //如果類沒有實例化對象 難道 就不能使用data了嗎? //解決上述問題 就要用到靜態(tài)成員函數(shù) //1、靜態(tài)成員函數(shù) 屬于類 就可以通過類名稱直接訪問 cout<<Data::getDataStatic()<<endl; //2、也可以通過對象名訪問(對象共享靜態(tài)成員函數(shù)) cout<<ob.getDataStatic()<<endl; }
注意:
1、靜態(tài)成員函數(shù)的目的 操作靜態(tài)成員數(shù)據(jù)。
2、靜態(tài)成員函數(shù) 不能訪問 非靜態(tài)成員數(shù)據(jù)。(靜態(tài)成員函數(shù)內部沒有this指針)
3、普通成員函數(shù) 可以操作 靜態(tài)成員數(shù)據(jù) 非靜態(tài)成員數(shù)據(jù)。
4、靜態(tài)成員變量 和 靜態(tài)成員函數(shù) 都有權限之分。
const修飾靜態(tài)成員
如果一個類的成員,既要實現(xiàn)共享,又要實現(xiàn)不可改變,那就用 static const 修飾
class Data { public: const static int data;//靜態(tài)成員變量(類內聲明) public: //靜態(tài)成員函數(shù) 屬于類 而不屬于對象 static int getDataStatic(void) { //num = 200;//err 靜態(tài)成員函數(shù) 不能訪問普通成員變量 return data; } }; //定義的時候 不需要加static const int Data::data=100;//類外定義+初始化 void test02() { //訪問 cout<<Data::data<<endl; //賦值 //Data::data = 200;//err data靜態(tài)成員只讀 cout<<Data::data<<endl; }
const修飾對象 叫常對象
const int num = 10;//系統(tǒng)不會給num開辟空間 num被放入符號表中 如果后期對&num 這時系統(tǒng)才會給num開辟空間
class Data { private: int data; mutable int num; public: //遍歷 成員的函數(shù) 不會去修改成員的值 //如果函數(shù)不會更改成員數(shù)據(jù) 就讓編譯器知道 這是一個const函數(shù) void myPrintData(void) const { //data =10000;//err const修飾函數(shù) 函數(shù)不能操作普通成員變量 cout<<this->data<<endl; //cout<<data<<endl; //mutable修飾的成員變量 可以修改 num = 200; } //編譯器認為 普通成員函數(shù) 存在修改成員變量 可能 void setData(int data) const { //this->data = data; return; } Data() { cout<<"無參構造"<<endl; } Data(int data) { this->data =data; cout<<"有參構造"<<endl; } Data(const Data &ob) { this->data = ob.data; cout<<"拷貝構造"<<endl; } ~Data() { cout<<"析構函數(shù)"<<endl; } }; void test03() { //常對象 const Data ob1(200); //常對象 只能調用const修飾的函數(shù) 遍歷成員數(shù)據(jù) ob1.setData(20000); ob1.myPrintData(); }
運行結果:
const修飾成員函數(shù)
用const修飾的成員函數(shù)時,const修飾this指針指向的內存區(qū)域,成員函數(shù)體內不可以修改本類中的任何普通成員變量, 當成員變量類型符前用mutable修飾時例外。
int myFun(void) const //const修飾的是成員函數(shù) {}//函數(shù)內部不能修改 普通成員變量 mutable修飾時例外
class Data2 { public: int a; mutable int b; public: Data2(int a, int b):a(a),b(b) { // this->a = a; // this->b = b; } //const修飾的是整個成員函數(shù) 表明在函數(shù)內部只能對數(shù)據(jù)成員 讀操作 void showData2(void) const { //a=100;//err //如果在const修飾的成員函數(shù)中 修改成員數(shù)據(jù)的值 請事先對成員數(shù)據(jù)進行mutable修飾 b = 200;//ok cout<<"a="<<a<<", b="<<b<<endl; } }; void test02() { Data2 ob(10,20); ob.showData2(); }
靜態(tài)成員案例
案例1:靜態(tài)成員 統(tǒng)計類 實例化對象的 個數(shù)
#include <iostream> using namespace std; class Data { public: Data() { cout<<"無參構造"<<endl; count++; } Data(const Data &ob) { cout<<"拷貝構造函數(shù)"<<endl; count++; } ~Data() { count--; cout<<"析構函數(shù)"<<endl; } static int count; }; int Data::count = 0; int main(int argc, char *argv[]) { Data ob1; Data ob2; { Data ob3; Data ob4; cout<<"對象的個數(shù):"<<Data::count<<endl; } cout<<"對象的個數(shù):"<<Data::count<<endl; return 0; }
運行結果:
單例模式
單例模式 所設計的類 只能實例化一個對象。
單例模式的步驟:
1、不允許Printer實例對象(把構造、拷貝構造函數(shù)私有化)
2、定義一個靜態(tài)對象指針 保存唯一的對象地址
3、定義一個靜態(tài) 成員函數(shù) 拿到唯一的對象的地址 方便外界使用
案例:
單例模式設計--打印機(重要)
步驟1:在單例類內部定義了一個Singleton類型的靜態(tài)對象,作為外部共享的唯一實例
步驟2:提供一個公共靜態(tài)的方法,讓客戶可以訪問它的唯一實例。
步驟3:為了防止在外部對實例化其他對象,將其默認構造函數(shù)和拷貝構造函數(shù)設計為私有
#include <iostream> using namespace std; class Printer { public: //2、提供一個方法 獲得單例指針 static Printer* getSignlePrint(void) { return signlePrint; } //4、設置功能函數(shù)(自定義) void printText(char *str) { cout<<"打印"<<str<<endl; count++; } int count; private: //1、定義一個靜態(tài)的 對象指針變量 保存唯一實例地址 static Printer *signlePrint; private: //3、防止 該類實例化其他對象 將構造函數(shù)全部 私有 Printer(){count=0;} Printer(const Printer &ob){} }; Printer *Printer::signlePrint = new Printer; int main(int argc, char *argv[]) { //打印任務1 Printer *p1 = Printer::getSignlePrint(); p1->printText("入職報告1"); p1->printText("體檢報告2"); p1->printText("離職證明3"); //打印任務2 Printer *p2 = Printer::getSignlePrint(); p2->printText("入職報告1"); p2->printText("體檢報告2"); p2->printText("離職證明3"); cout<<"打印任務數(shù)量:"<<p2->count<<endl; return 0; }
運行結果:
到此這篇關于C++簡明圖解分析靜態(tài)成員與單例設計模式的文章就介紹到這了,更多相關C++靜態(tài)成員內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
直觀理解C語言中指向一位數(shù)組與二維數(shù)組的指針
這篇文章主要介紹了直觀理解C語言中指向一位數(shù)組與二維數(shù)組的指針,數(shù)組指針是C語言入門學習過程中的重點和難點,需要的朋友可以參考下2016-05-05