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
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...