C++ Primer 類的靜態成員

歡迎閱讀我的 【C++Primer】專欄

專欄簡介:本專欄主要面向C++初學者,解釋C++的一些基本概念和基礎語言特性,涉及C++標準庫的用法,面向對象特性,泛型特性高級用法。通過使用標準庫中定義的抽象設施,使你更加適應高級程序設計技術。希望對讀者有幫助!

在這里插入圖片描述
在這里插入圖片描述

目錄

  • 7.6 類的靜態成員
    • 聲明靜態成員
    • 使用類的靜態成員
    • 靜態成員的類內初始化
    • 靜態成員能用于某些場景,而普通成員不能

7.6 類的靜態成員

有的時候類需要它的一些成員與類本身直接相關,而不是與類的各個對象保持關聯。例如,一個銀行賬戶類可能需要一個數據成員來表示當前的基準利率。在此例中,我們希望利率與類關聯,而非與類的每個對象關聯。從實現效率的角度來看,沒必要每個對象都存儲利率信息。而且更加重要的是,一旦利率浮動,我們希望所有的對象都能使用新值。

聲明靜態成員

我們通過在成員的聲明之前加上關鍵字static使得其與類關聯在一起。和其他成員一樣,靜態成員可以是public的或private的。靜態數據成員的類型可以是常量、引用、指針、類類型等。

舉個例子,我們定義一個類,用它表示銀行的賬戶記錄:

class Account{
public:
void calculate(){amount+=amount*interestRate;}
static double rate(){return interestRate;}
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();

類的靜態成員存在于任何對象之外,對象中不包含任何與靜態數據成員有關的數據。因此,每個Account對象將包括兩個數據成員:owner和amount。只存在一個interestRate對象而且它被所有Account對象共享。

類似的,靜態成員函數也不與任何對象綁定在一起,它們不包含this指針。作為結靜態成員函數不能聲明成const的,而且我們也不能在static函數體內使用this。這一限制既適用于this的顯式使用,也對調用非靜態成員的隱式使用有效。

使用類的靜態成員

我們使用作用域運算符直接訪問靜態成員:

double r;
r =Account::rate();//使用作用域運算符訪問靜態成員

雖然靜態成員不屬于類的某個對象,但是我們仍然可以使用類的對象、引用或者指針來訪問靜態成員:

Account ac1;
Account *ac2=&ac1;
//調用靜態成員函數rate的等價形式
r=ac1.rate();//通過Account的對象或引用
r=ac2->rate();//通過指向Account對象的指針

成員函數不用通過作用域運算符就能直接使用靜態成員:

class Account{
public:
void calculate(){amount+=amount*interestRate;}
private:
static double interestRate;
//其他成員與之前的版本一致
};定義靜態成員和其他的成員函數一樣,我們既可以在類的內部也可以在類的外部定義靜態成員函數。當在類的外部定義靜態成員時,不能重復static關鍵字,該關鍵宇只出現在類內部的聲明語句:```cpp
void Account::rate(double newRate)
{interestRate=newRate;
}因為靜態數據成員不屬于類的任何一個對象,所以它們并不是在創建類的對象時被定義的。這意味著它們不是由類的構造函數初始化的。而且一般來說,我們不能在類的內部初始化靜態成員。相反的,必須在類的外部定義和初始化每個靜態成員。和其他對象一樣,-個靜態數據成員只能定義一次。類似于全局變量,靜態數據成員定義在任何函數之外。因此一旦它被定義,就將一直存在于程序的整個生命周期中。我們定義靜態數據成員的方式和在類的外部定義成員函數差不多。我們需要指定對象的類型名,然后是類名、作用域運算符以及成員自己的名字:```cpp
//定義并初始化一個靜態成員
double Account::interestRate=initRate();

這條語句定義了名為interestRate的對象,該對象是類Account的靜態成員,其類型是double。從類名開始,這條定義語句的剩余部分就都位于類的作用域之內了。因此,我們可以直接使用initRate函數。注意,雖然initRate是私有的,我們也能用它初始化interestRate。和其他成員的定義一樣interestRate的定義也可以訪問類的私有成員。

要想確保對象只定義一次,最好的辦法是把靜態數據成員的定義與其他非內聯函數的定義放在同一個文件中。

靜態成員的類內初始化

通常情況下,類的靜態成員不應該在類的內部初始化。然而,我們可以為靜態成員提供const整數類型的類內初始值,不過要求靜態成員必須是字面值常量類型的constexpr(參見7.5.6節,第267頁)。初始值必須是常量表達式,因為這些成員本身就是常量表達式,所以它們能用在所有適合于常量表達式的地方。例如,我們可以用一個初始化了的靜態數據成員指定數組成員的維度:

class Account{
public:
static double rate(){return interestRate;}
static void rate(double);
private:
static constexpr int period=30;//period是常量表達式
double daily_tbl[period];
}

如果某個靜態成員的應用場景僅限于編譯器可以替換它的值的情況,則一個初始化的const或constexpr static不需要分別定義。相反,如果我們將它用于值不能替換的場景中,則該成員必須有一條定義語句。例如,如果period的唯一用途就是定義daily_tbl的維度,則不需要在hccount外面專門定義period。此時,如果我們忽略了這條定義,那么對程序非常微小的改動也可能造成編譯錯誤,因為程序找不到該成員的定義語句。舉個例子,當需要把Account::period傳遞給一個接受const int &的函數時,必須定義period。如果在類的內部提供了一個初始值,則成員的定義不能再指定一個初始值了:

//一個不帶初始值的靜態成員的定義
constexpr intRccount::period;//初始值在類的定義肉提供

即使一個常量靜態數據成員在類內部被初始化了,通常情況下也應該在類的外部定義一下該成員。

靜態成員能用于某些場景,而普通成員不能

如我們所見,靜態成員獨立于任何對象。因此,在某些非靜態數據成員可能非法的場合,靜態成員卻可以正常地使用。舉個例子,靜態數據成員可以是不完全類型。特別的,靜態數據成員的類型可以就是它所屬的類類型。而非靜態數據成員則受到限制,只能聲明成它所屬類的指針或引用:

class Bar{
public:
// ...
private:
static Bar meml;//正確:靜態成員可以是不完全類型
Bar* mem2;//正確:指針成員可以是不完全類型
Bar mem3;//錯誤:數據成員必須是完全類型
}靜態成員和普通成員的另外一個區別是我們可以使用靜態成員作為默認實參:```cpp
class Screen{
public:
//bkground表示一個在類中稍后定義的靜態成員
Screen &clear(char=bkground);
private::
static const char bkground;
}

非靜態數據成員不能作為默認實參,因為它的值本身屬于對象的一部分,這么做的結果是無法真正提供一個對象以便從中獲取成員的值,最終將引發錯誤。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70412.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70412.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70412.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java——super

在Java中,super關鍵字用于引用父類的成員(屬性、方法或構造器)。它在繼承關系中非常重要,主要用于以下幾種場景: 1. 調用父類的構造器 在子類的構造器中,可以使用super關鍵字調用父類的構造器。super()必須…

Unity 全局屏幕點擊特效

思路: 1、生成一個點擊特效實例,每點擊屏幕,就調整特效實例的位置并控制特效的顯隱狀態即可。 2、需要注意要保證在編輯器開發時或手機上運行時都要顯示點擊效果。 方案一 (推薦) using UnityEngine; using UnityEn…

什么是業務流程分類框架

業務流程分類框架是一個用于組織和系統化地分類業務流程的結構化方法。它旨在幫助企業理解、管理、分析和改進其運營流程。 可以把它想象成一個圖書館的圖書分類系統,幫助快速找到和理解不同類型的書籍。對于業務流程來說,分類框架幫助快速了解不同類型的…

基于springboot校園健康系統的設計與實現(源碼+文檔)

大家好我是風歌,今天要和大家聊的是一款基于springboot的園健康系統的設計與實現。項目源碼以及部署相關請聯系風歌,文末附上聯系信息 。 項目簡介: 基于springboot校園健康系統的設計與實現的主要使用者管理員具有最高的權限,通…

【Leetcode】平衡二叉樹

平衡二叉樹 題目 思路與代碼實現 常規解法: int max(int a,int b){return a>b?a:b;}int maxDepth(struct TreeNode* root) {if(rootNULL)return 0;return 1max(maxDepth(root->left),maxDepth(root->right)); }bool isBalanced(struct TreeNode* root)…

【AI實踐】阿里百煉文本對話Agent安卓版搭建

環境:安卓手機運行環境;WinsurfAI編程工具;阿里百煉提前創建Agent應用; 耗時:2小時; 1,新建安卓項目 完成文本輸入,并將輸入的文字顯示出來。 2,安裝SDK 參考文檔 安…

一文讀懂Docker之Docker Compose

目錄 一、Docker Compose簡介 二、Docker Compose的安裝和基本使用 1、Docker Compose的安裝 步驟一、下載docker-compose 步驟二、新增可執行權限 步驟三、查看是否安裝成功 2、Docker Compose的基本使用 (1)、docker-compose up (2)、docker-compose ps (3)、docke…

WordPress“更新失敗,響應不是有效的JSON響應”問題的修復

在使用WordPress搭建網站時,許多人在編輯或更新文章時,可能會遇到一個提示框,顯示“更新失敗,響應不是有效的JSON響應”。這個提示信息對于不了解技術細節的用戶來說,太難懂。其實,這個問題并不復雜&#x…

信息學奧賽一本通 1973 【16NOIP普及組】買鉛筆 | 洛谷 P1909 [NOIP 2016 普及組] 買鉛筆

【題目鏈接】 ybt 1973 【16NOIP普及組】買鉛筆 洛谷 P1909 [NOIP 2016 普及組] 買鉛筆 【題目考點】 1. 簡單數學 2. 數組 3. 向上取整 <cmath>中有函數double ceil(double x)&#xff0c;求x向上取整的值。 如果求正整數 ? a b ? \lceil \frac{a}{b} \rceil ?…

C++中的.*運算符

看運算符重載的時候&#xff0c;看到這一句 .* :: sizeof ?: . 注意以上5個運算符不能重載。 :: sizeof ?: . 這四個好理解&#xff0c;畢竟都學過&#xff0c;但.*是什么&#xff1f; 于是自己整理了一下 .* 是一種 C 中的運算符&#xff0c;稱為指針到成…

【JavaEE進階】MyBatis通過注解實現增刪改查

目錄 &#x1f343;前言 &#x1f340;打印日志 &#x1f334;傳遞參數 &#x1f38b;增(Insert) &#x1f6a9;返回主鍵 &#x1f384;刪(Delete) &#x1f332;改(Update) &#x1f333;查(Select) &#x1f6a9;起別名 &#x1f6a9;結果映射 &#x1f6a9;開啟駝…

【分布式理論14】分布式數據庫存儲:分表分庫、主從復制與數據擴容策略

文章目錄 一、分表分庫1. 數據分表的必要性與方式2. 數據分庫原則與優勢 二、主從復制1. 讀寫分離架構設計2. 數據復制方式3. MySQL實現主從復制4. MySQL主從復制實踐與高可用方案 三、數據擴容 隨著業務的不斷發展和數據量的增長&#xff0c;傳統的單機關系型數據庫已經逐漸不…

vxe-grid 通過配置式給單元格字段格式化樹結構數據,轉換樹結構節點

vxe-grid 通過配置式給單元格字段格式化樹結構數據&#xff0c;轉換樹結構節點 比如用戶自定義配置好的數據源&#xff0c;通過在列中配置好數據&#xff0c;全 json 方式直接返回給前端渲染&#xff0c;不需要寫任何格式化方法。 官網&#xff1a;https://vxetable.cn npm i…

延遲任務的11種實現方式(下)!!

接上文&#xff1a; Redisson的RDelayedQueue Redisson他是Redis的兒子&#xff08;Redis son&#xff09;&#xff0c;基于Redis實現了非常多的功能&#xff0c;其中最常使用的就是Redis分布式鎖的實現&#xff0c;但是除了實現Redis分布式鎖之外&#xff0c;它還實現了延遲…

BS5852英國家具防火安全條款主要包括哪幾個方面呢?

什么是BS5852檢測&#xff1f; BS5852是英國針對家用家具的強制性安全要求&#xff0c;主要測試家具在受到燃燒香煙和火柴等火源時的可燃性。這個標準通常分為四個部分進行測試&#xff0c;但實際應用中主要測試第一部分和第二部分&#xff0c;包括煙頭測試和利用乙炔火焰模擬…

如何使用Spark SQL進行復雜的數據查詢和分析

使用Spark SQL進行復雜的數據查詢和分析是一個涉及多個步驟和技術的過程。以下是如何使用Spark SQL進行復雜數據查詢和分析的詳細指南&#xff1a; 一、準備階段 環境搭建&#xff1a; 確保已經安裝并配置好了Apache Spark環境。準備好數據源&#xff0c;可以是CSV文件、JSON…

iOS事件傳遞和響應

背景 對于身處中小公司且業務不怎么復雜的程序員來說&#xff0c;很多技術不常用&#xff0c;你可能看過很多遍也都大致了解&#xff0c;但是實際讓你講&#xff0c;不一定講的清楚。你可能說&#xff0c;我以獨當一面&#xff0c;應對自如了&#xff0c;但是技術的知識甚多&a…

FFmpeg 源碼編譯安裝

參考&#xff1a; https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu Linux (Ubuntu) 下載 FFmpeg 源碼&#xff0c;并將其解壓&#xff0c;這里我將它放在 ~/ffmpeg_source 目錄下&#xff1b; cd ~/ffmpeg_sources wget -O ffmpeg-snapshot.tar.bz2 https://ffmpeg.org…

【pytest】編寫自動化測試用例命名規范README

API_autoTest 項目介紹 1. pytest命名規范 測試文件&#xff1a; 文件名需要以 test_ 開頭或者以 _test.py 結尾。例如&#xff0c;test_login.py、user_management_test.py 這樣的命名方式&#xff0c;pytest 能夠自動識別并將其作為測試文件來執行其中的測試用例。 測試類…

Windows桌面系統管理5:Windows 10操作系統注冊表

Windows桌面系統管理0&#xff1a;總目錄-CSDN博客 Windows桌面系統管理1&#xff1a;計算機硬件組成及組裝-CSDN博客 Windows桌面系統管理2&#xff1a;VMware Workstation使用和管理-CSDN博客 Windows桌面系統管理3&#xff1a;Windows 10操作系統部署與使用-CSDN博客 Wi…