c++中的 static 關鍵字

来源:https://www.cnblogs.com/nbk-zyc/archive/2020/02/15/12305170.html
-Advertisement-
Play Games

註:若沒有特指是 靜態成員時,預設都是普通成員; 1 類中的普通成員 類中的成員變數 和 成員函數 是分開存儲的。其中, 1)每個對象都有獨立的成員變數;成員變數可以存儲在 棧空間、堆空間、全局數據區; 2)所有對象共用類的成員函數;成員函數 只能存儲在 代碼段; 2 類中的靜態成員(static) ...


註:若沒有特指是 靜態成員時,預設都是普通成員;

1 類中的普通成員

  類中的成員變數 和 成員函數 是分開存儲的。其中,

    1)每個對象都有獨立的成員變數;成員變數可以存儲在 棧空間、堆空間、全局數據區;

    2)所有對象共用類的成員函數;成員函數 只能存儲在 代碼段;

2 類中的靜態成員(static

  類中的靜態成員

    1、用 static關鍵字 修飾;

    2、可以用 類名::成員名  訪問 靜態成員;

    3、靜態成員  屬於  整個類;

    4、靜態成員 是所屬類的成員,其它類不能訪問;

    5、靜態成員的記憶體分配 是 唯一的;

  1) 靜態成員變數 

    特征:1、靜態成員變數  屬於  整個類所有

       2、靜態成員變數的生命周期不依賴任何對象;(靜態成員變數的生命周期在程式的運行期)

       3、所有對象共用類的靜態成員變數;

       4、可以通過  類名  直接訪問公有的靜態成員變數;

       5、可以通過 對象名  訪問公有的靜態成員變數;

       6、靜態成員變數  需要在類外單獨分配空間;(類內聲明、類外定義並初始化)

          7、靜態成員變數  在程式內部位於全局數據區,不計入類的記憶體計算。

    原因/好處:使用靜態成員變數實現多個對象之間的數據共用不會破壞隱藏的原則,保證了安全性還可以節省記憶體

    使用方法:

      1、在類的內部,使用 static 修飾普通成員變數;

      2、在類的外部(全局作用域),使用 Type ClassName::VarName = value 初始化,並申請存儲空間;

         註:靜態成員變數不屬於類的任何對象,所以並不是對象建立時被定義的,所以它不能由類的構造函數初始化,一般也不能在類內初始化

 1 /*
 2     靜態成員變數 只能在類的內部聲明,在類的外部(全局區)定義和初始化;
 3 */
 4 
 5 #include <iostream>
 6 
 7 using namespace std;
 8 
 9 class Test{
10 public:
11     int GetA() const{return a;}
12 private:
13     static int a;  // 靜態成員變數
14 };
15 //int Test::a;如果這樣定義不賦予初值,則初值為零
16 int Test::a = 1;
17 
18 int main(int argc, char *argv[])
19 {
20     Test T;
21 
22     cout << T.GetA() << endl;
23 
24     return 0;
25 }

  靜態成員變數 被類的所有對象共用,包括派生類對象;

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class Base{
 6 public:
 7     static int a;  // 靜態成員變數
 8 };
 9 
10 // int Test::a;如果這樣定義不賦予初值,則初值為零
11 int Base::a;
12 
13 class Derived : public Base{
14  
15 };
16 
17 
18 int main(int argc, char *argv[])
19 {
20     Base B;
21     Derived D;
22 
23     B.a++;
24     cout << B.a << endl;   // 1
25     D.a++;
26     cout << D.a << endl;   // 2
27 
28     return 0;
29 }

  靜態成員變數可以作為普通成員函數的預設形參,而普通成員變數則不可以;

1 class Test{
2 public:
3     static int a;  //靜態成員變數
4     int b;
5     void fun_1(int i = a); //正確
6     //void fun_2(int i = b); //報錯
7 };

  靜態成員變數的類型 可以是所屬類的類型,而普通成員變數則不可以。普通成員變數只能聲明為 所屬類類型的 指針或引用;

1 class Test{
2 public:
3     static Test a;  //正確
4     Test b;  //報錯
5     Test *pTest;  //正確
6     Test &m_Test;  //正確
7     static Test *pStaticObject;  //正確
8 };

  靜態成員變數在const函數中可以修改,而普通的成員變數是萬萬不能修改的;

 1 /*
 2   const修飾的是當前this指針所指向的對象是const,但是靜態成員變數不屬於任何類的對象,它被類的所有對象修改,所以this指針不修飾靜態的成員變數,所以可以更改。
 3 */
 4 class Test{
 5 public:
 6     static int a;
 7     int b;
 8 public:
 9         Test():b(0){}
10     void test() const
11     {
12         a++;
13         //b++;  // err  // const指的是不能修改當前調用該函數對象的成員變數
14     }
15 };
16 
17 int Test::a;

 2)靜態成員函數

    特征:1、靜態成員函數  屬於  整個類所有;

       2、所有對象共用類的靜態成員函數;

       2、可以通過  類名  直接訪問公有的靜態成員函數;

       3、可以通過 對象名  訪問公有的靜態成員函數;

       4、靜態成員函數 只能 訪問靜態成員,不能訪問  非靜態成員;

       5、靜態成員函數沒有this指針,也就是說靜態成員函數不能使用修飾符(也就是函數後面的const關鍵字)

    原因:處理靜態成員變數; 

    使用方法:直接用 static 修飾 普通成員函數(類內聲明時),不需要 static 修飾(類外定義時);

    總結:

     案例分析:

  1 /**
  2  * 統計某班選修課考試的平均成績
  3 */
  4 
  5 #include <iostream>
  6 #include <string>
  7 
  8 using namespace std;
  9 
 10 class Student
 11 {
 12 private:
 13     string name;    // 姓名
 14     string gender;  // 性別
 15     float score;    // 分數
 16     string subject; // 課程
 17     static int total_counts;        // 總人數
 18     static float chinese_scores;    // 語文分數
 19     static int chinese_counts;      // 語文課人數
 20     static float math_scores;       // 數學分數
 21     static int math_counts;         // 數學課人數
 22 public:
 23     Student(string name, string gender, float score, string subject);
 24     ~Student();
 25     static float aveScores(string subject);
 26     void printStudentInfo();
 27     void printAveScores();
 28 };
 29 int Student::total_counts = 0;
 30 float Student::chinese_scores = 0;
 31 int Student::chinese_counts = 0;
 32 float Student::math_scores = 0;
 33 int Student::math_counts = 0;
 34 
 35 Student::Student(string name, string gender, float score, string subject)
 36 {
 37     this->name = name;
 38     this->gender = gender;
 39     this->score = score;
 40     this->subject = subject;
 41 
 42     if(subject == "chinese" || subject == "語文")
 43     {
 44         chinese_scores += score;
 45         chinese_counts++;
 46     }
 47     else if(subject == "math" || subject == "數學")
 48     {
 49         math_scores += score;
 50         math_counts++;
 51     }
 52     else
 53     {
 54         cout << "this is no the subect:" << subject << endl;
 55     }
 56     total_counts += (chinese_counts +  math_counts);
 57 }
 58 
 59 Student::~Student()
 60 {
 61     total_counts--;
 62     chinese_counts--;
 63     math_counts--;
 64 }
 65 
 66 float Student::aveScores(string subject)
 67 {
 68     float ave_score = 0;
 69 
 70     if(chinese_counts > 0 && subject == "chinese" || subject == "語文")
 71     {
 72        ave_score = (chinese_scores / chinese_counts);
 73        //cout << subject << "\t" << chinese_counts << "\t" << chinese_scores << endl;
 74     }
 75     else if(math_counts > 0 && subject == "math" || subject == "數學")
 76     {
 77        ave_score = (math_scores / math_counts);
 78        //cout << subject << "\t" <<math_counts << "\t" << math_scores << endl;
 79     }
 80 
 81     return ave_score;
 82 }
 83 
 84 void Student::printStudentInfo()
 85 {
 86     cout << name << "\t" << gender << "\t" << score << "\t" << subject << endl;
 87 }
 88 
 89 void Student::printAveScores()
 90 {
 91     cout <<subject  << " average score: " << aveScores(subject) << endl;
 92 }
 93 
 94 int main(int argc, char const *argv[])
 95 {
 96     const int SIZE = 5;
 97     Student stu[SIZE] = 
 98         {
 99             Student("10001", "male", 92, "語文"),
100             Student("10002", "male", 91, "數學"),
101             Student("10003", "male", 91, "數學"),
102             Student("10004", "male", 93, "語文"),
103             Student("10005", "male", 92, "語文"),
104         };
105 
106     for(int i = 0; i < SIZE; i++)
107     {
108         stu[i].printStudentInfo();
109     }
110 
111    stu[0].printAveScores();
112    stu[1].printAveScores();
113 
114    cout << "語文" << " average score: " << Student::aveScores("語文") << endl;
115    cout << "數學" << " average score: " << Student::aveScores("數學") << endl;
116 
117     return 0;
118 }
靜態成員的案例分析

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • isinstance和issubclass isinstance(obj,cls)檢查是否obj是否是類 cls 的對象 class Foo(object): pass obj = Foo() isinstance(obj, Foo) issubclass(sub, super)檢查sub類是否是 ...
  • 楔子 你現在是一家游戲公司的開發人員,現在需要你開發一款叫做<人狗大戰>的游戲,你就思考呀,人狗作戰,那至少需要2個角色,一個是人, 一個是狗,且人和狗都有不同的技能,比如人拿棍打狗, 狗可以咬人,怎麼描述這種不同的角色和他們的功能呢? 你搜羅了自己掌握的所有技能,寫出了下麵的代碼來描述這兩個角色 ...
  • 包 包是一種通過使用‘.模塊名’來組織python模塊名稱空間的方式。 1. 無論是import形式還是from...import形式,凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提高警覺:這是關於包才有的導入語法 2. 包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是 ...
  • 什麼是模塊? 常見的場景:一個模塊就是一個包含了python定義和聲明的文件,文件名就是模塊名字加上.py的尾碼。 但其實import載入的模塊分為四個通用類別: 1 使用python編寫的代碼(.py文件) 2 已被編譯為共用庫或DLL的C或C++擴展 3 包好一組模塊的包 4 使用C編寫並鏈接到 ...
  • https://www.cnblogs.com/WUXIAOCHANG/p/10886534.html https://blog.csdn.net/pengjwhx/article/details/84867112 ...
  • 楔子 在講今天的內容之前,我們先來講一個故事,講的什麼呢?從前有座山,山裡有座廟,廟裡有個老和尚講故事,講的什麼呢?從前有座山,山裡有座廟,廟裡有個老和尚講故事,講的什麼呢?從前有座山,山裡有座廟,廟裡有個老和尚講故事,講的什麼呢?從前有座山,山裡有座廟,廟裡有個老和尚講故事,講的什麼呢...... ...
  • 楔子 在講新知識之前,我們先來複習複習函數的基礎知識。 問:函數怎麼調用? 函數名() 如果你們這麼說。。。那你們就對了!好了記住這個事兒別給忘記了,咱們繼續談下一話題。。。 來你們在自己的環境里列印一下自己的名字。 你們是怎麼打的呀? 是不是print('xxx'),好了,現在你們結合我剛剛說的函 ...
  • 第一個Django程式 從本章節開始將通過實現一個投票應用程式,來讓用戶逐步的瞭解Django。這個程式由兩步分組成: 公共站點,允許用戶訪問進行投票,和查看投票。 站點管理,允許添加,刪除,修改投票信息。 1、創建項目 本文繼承前一篇章節的環境(centos 7 python3.6.2 Djang ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...