C++的靜態(tài)成員變量和靜態(tài)成員函數(shù)你了解多少
靜態(tài)成員變量
這里先引用GeeksforGeeks的一段內(nèi)容:
Static data members are class members that are declared using static keywords. A static member has certain special characteristics. These are:
- Only one copy of that member is created for the entire class and is shared by all the objects of that class, no matter how many objects are created.
- It is initialized before any object of this class is being created, even before main starts.
- It is visible only within the class, but its lifetime is the entire program
語(yǔ)法: static data_type data_member_name;
靜態(tài)變量在任何類(lèi)對(duì)象創(chuàng)建前初始化
我們看代碼示例,一碼勝千言
#include <iostream> using namespace std; class A { public: A() { cout << "A constructed" << endl; } }; class B { static A a; public: B() { cout << "B constructed" << endl; } }; int main() { B b; return 0; } // output B constructed
我們看到B類(lèi)有一個(gè)靜態(tài)成員A類(lèi),但是在創(chuàng)建B的對(duì)象時(shí)并沒(méi)有調(diào)用A的構(gòu)造函數(shù),原因很簡(jiǎn)單,即在類(lèi)B中僅僅聲明(declare)了靜態(tài)類(lèi)A,但沒(méi)有在類(lèi)外定義(define)它。 如果我們?cè)陟o態(tài)成員變量定義前使用它,那么會(huì)編譯報(bào)錯(cuò),這和代碼塊中的靜態(tài)變量不同,代碼塊中的靜態(tài)變量會(huì)有常量初始化的過(guò)程,代碼示例如下。
#include <iostream> using namespace std; class A { public: int x; A() { cout << "A constructed" << endl; } }; class B { static A a; public: B() { cout << "B constructed" << endl; } static A getA() {return a;} }; int main() { B b; // A a = b.getA(); // ERROR Compiler Error: undefined reference to `B::a' static int n; cout << n << endl; // ok 0 return 0; }
定義靜態(tài)成員變量
我們?cè)陬?lèi)內(nèi)定義靜態(tài)成員變量時(shí)需要 static,在類(lèi)外定義鏡頭成員變量時(shí)不用 static,語(yǔ)法如下。
class X { static int n; }; // declaration (uses 'static') int X::n = 1; // definition (does not use 'static')
這里需要注意幾點(diǎn):
- const靜態(tài)成員變量無(wú)法在類(lèi)內(nèi)初始化
- 靜態(tài)成員變量只能在方法外定義,且一定要定義完才能對(duì)起引用。
我們考慮下為什么不能在聲明中初始化靜態(tài)變量,這是因?yàn)槁暶髅枋鰜?lái)如何分配內(nèi)存,但不分配內(nèi)存。這里我們還是使用上面代碼的例子來(lái)說(shuō)明。
using namespace std; class A { public: int x; A() { cout << "A's constructor called " << endl; } }; class B { static A a; public: B() { cout << "B's constructor called " << endl; } static A getA() { return a; } }; A B::a; // definition of a int main() { B b1, b2, b3; A a = b1.getA(); cout << a.x << endl; // 0 return 0; }
output
A's constructor called B's constructor called B's constructor called B's constructor called 0
從上述結(jié)果我們也可以看出來(lái)靜態(tài)成員變量確實(shí)在創(chuàng)建類(lèi)對(duì)象之前初始化。
使用靜態(tài)成員變量
有兩種方法可以引用靜態(tài)成員變量,<類(lèi)對(duì)象名>.<靜態(tài)數(shù)據(jù)成員名>
或 <類(lèi)類(lèi)型名>::<靜態(tài)數(shù)據(jù)成員名>
To refer to a static member m of class T, two forms may be used: qualified name T::m or member access expression E.m or E->m, where E is an expression that evaluates to T or T* respectively. When in the same class scope, the qualification is unnecessary:
struct X { static void f(); // declaration static int n; // declaration }; X g() { return X(); } // some function returning X void f() { X::f(); // X::f is a qualified name of static member function g().f(); // g().f is member access expression referring to a static member function } int X::n = 7; // definition void X::f() // definition { n = 1; // X::n is accessible as just n in this scope }
類(lèi)對(duì)象共享靜態(tài)成員
靜態(tài)類(lèi)成員有一個(gè)特點(diǎn):無(wú)論創(chuàng)建了多少個(gè)對(duì)象,程序都只創(chuàng)建一個(gè)靜態(tài)類(lèi)變量副本。也就是說(shuō),類(lèi)的所有對(duì)象共享同一個(gè)靜態(tài)成員。靜態(tài)數(shù)據(jù)成員和普通數(shù)據(jù)成員一樣遵從public,protected,private訪問(wèn)規(guī)則;
接下來(lái)看另一個(gè)代碼示例
#include <iostream> using namespace std; class A { public: static int x; int y; static void f() { // y++; Error invalid use of member 'y' in static member function x++; cout << "A static function, x = " << x << endl; } }; int A::x; int main() { A a; cout << "x = " << A::x << endl; cout << "x = " << a.x << endl; A::f(); a.f(); return 0; }
output
x = 0 x = 0 A static function, x = 1 A static function, x = 2
const constexpr
C++提供了多種在類(lèi)中定義常量的方式,其中比較常用的有 const
,constexpr
和enum
class X { // method1 const const static int n = 1; const static int m{2}; // since C++11 const static int k; // ok // method2 enum enum {Month=12}; // method3 constexpr constexpr static int arr[] = { 1, 2, 3 }; // OK constexpr static std::complex<double> n = {1,2}; // OK constexpr static int k; // Error: constexpr static requires an initializer }; const int X::k = 3;
其中注意:
1.使用 enum 時(shí)并不會(huì)創(chuàng)建數(shù)據(jù)成員,即所有的對(duì)象中都不包括枚舉,另外Month知識(shí)一個(gè)符號(hào)名稱(chēng),在作用于為整個(gè)類(lèi)的代碼中遇到它是,編譯器將用12來(lái)替代它。而且只能是整數(shù)。
2.使用 constexpr 來(lái)創(chuàng)建類(lèi)常量時(shí),一定要給其定義,不能只是聲明,而const可以只是聲明,不用給出定義。
靜態(tài)成員函數(shù)
#include <iostream> using namespace std; class Person { public: Person() {}; Person(char *name, int age); void show(); static int getTotal(); private: static int m_total; char *m_name; int m_age; }; Person::Person(char *name, int age) : m_name(name), m_age(age) { m_total++; } void Person::show() { cout << m_name << "的年齡是" << m_age << ", 總?cè)藬?shù)是" << m_total << endl; } int Person::getTotal() { return m_total; } // 一定要先初始化 int Person::m_total = 0; int main() { Person *p1 = new Person("Alice", 18); Person *p2 = new Person("Bob", 18); p1->show(); p2->show(); int total1 = Person::getTotal(); int total2 = p1->getTotal(); cout << "total1 = " << total1 << ", total2 = " << total2 << endl; return 0; }
靜態(tài)成員函數(shù)與普通成員函數(shù)的根本區(qū)別在于:普通成員函數(shù)有 this 指針,可以訪問(wèn)類(lèi)中的任意成員;而靜態(tài)成員函數(shù)沒(méi)有 this 指針,只能訪問(wèn)靜態(tài)成員(包括靜態(tài)成員變量和靜態(tài)成員函數(shù))。這里要注意的是普通的成員函數(shù)也能訪問(wèn)靜態(tài)成員變量。這一點(diǎn)上和Java中的static用法很像。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- C++的靜態(tài)成員變量和靜態(tài)成員函數(shù)詳解
- C++類(lèi)的靜態(tài)成員變量與靜態(tài)成員函數(shù)詳解
- 詳解c++ 靜態(tài)成員變量
- C++中靜態(tài)成員函數(shù)與靜態(tài)成員變量(static )
- C++靜態(tài)成員變量和靜態(tài)成員函數(shù)的使用方法總結(jié)
- C++靜態(tài)成員函數(shù)不能調(diào)用非靜態(tài)成員變量(詳解)
- 關(guān)于C++靜態(tài)成員函數(shù)訪問(wèn)非靜態(tài)成員變量的問(wèn)題
- C++分析講解類(lèi)的靜態(tài)成員變量是什么
相關(guān)文章
C語(yǔ)言簡(jiǎn)明清晰講解結(jié)構(gòu)體
C語(yǔ)言結(jié)構(gòu)體(Struct)從本質(zhì)上講是一種自定義的數(shù)據(jù)類(lèi)型,只不過(guò)這種數(shù)據(jù)類(lèi)型比較復(fù)雜,是由 int、char、float 等基本類(lèi)型組成的。你可以認(rèn)為結(jié)構(gòu)體是一種聚合類(lèi)型2022-05-05C語(yǔ)言對(duì)冒泡排序進(jìn)行升級(jí)介紹
大家好,本篇文章主要講的是C語(yǔ)言對(duì)冒泡排序進(jìn)行升級(jí)介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01華為云CodeArts?IDE?Online快速入門(mén)和使用
華為云CodeArts?IDE?Online服務(wù),提供了可隨時(shí)隨地編碼的云上開(kāi)發(fā)環(huán)境,同時(shí)具備開(kāi)放的生態(tài)和獨(dú)立插件市場(chǎng),本文主要介紹了華為云CodeArts?IDE?Online快速入門(mén)和使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08利用OpenCV實(shí)現(xiàn)局部動(dòng)態(tài)閾值分割
這篇文章主要為大家詳細(xì)介紹了利用OpenCV實(shí)現(xiàn)局部動(dòng)態(tài)閾值分割,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01C++關(guān)鍵字volatile學(xué)習(xí)筆記
這篇文章主要為大家介紹了C++關(guān)鍵字volatile學(xué)習(xí)筆記,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10華為機(jī)試題之統(tǒng)計(jì)單詞個(gè)數(shù)實(shí)例代碼
這篇文章主要介紹了華為機(jī)試題之統(tǒng)計(jì)單詞個(gè)數(shù)實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05淺談C語(yǔ)言函數(shù)調(diào)用參數(shù)壓棧的相關(guān)問(wèn)題
下面小編就為大家?guī)?lái)一篇淺談C語(yǔ)言函數(shù)調(diào)用參數(shù)壓棧的相關(guān)問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09