你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

C++——静态成员变量和静态成员函数

[复制链接]
gaosmile 发布时间:2020-8-9 21:02
不知不觉,又到周末了;上次在交流群里,答应给大家免费送开发板,一开始认为板子够送,但是昨天整理了一下,然后送了大概十几个网友就不够送了,还有十几个网友没得到板子,这里说声实在抱歉,下次有机会搞活动再送给大家好玩的板子:
微信图片_20200809210128.png
上图的板子有最近买的,也有以前买的(stm32、esp8266、51、esp32、小熊派、合宙的cat1、树莓派3b+);说实话,这些板子买来,一直放在那里吃灰,后期自己的方向也不玩硬件开发板啥的;所以上面的板子都送给了公众号读者在校生,让这些板子发挥它们最大的价值,板子也会在最近慢慢一一送出去;赠人与玫瑰,手有余香!
好了回归主题,今天继续分享c++的文章,学习还是不能落下,flag未完成,任务艰巨,好好学习。
一、静态成员变量:
平时我们在写类的时候,类中的成员变量,我们一般是通过对象名来访问public成员变量的,一般private(私有)的成员变量,对象是不能直接访问的;同时我们要明白每个对象的成员变量都是专属的,而且成员变量是不能在对象之间共享的,这就是专属性。下面我们来做一个小的程序需求来慢慢引出静态成员变量:
  • 统计在程序运行期间某个类的对象数目
  • 要保证该程序的安全性(不能使用全局变量)
  • 随时可以获取当前对象的数目
    + u. t0 h. O# y! Q% p  A9 X
代码版本一:
#include <stdio.h>5 ?# Y7 s7 X/ J( @* ?
class Test/ q# @( l+ v" @3 k7 L
{) y8 \8 \' _  x5 F' d0 X. Z0 t8 t. T
private:! }; b( q9 n& B$ G' ]
       int mCount;& n3 p- ?/ `5 e5 [( L7 e9 k6 i5 i
public:
5 p2 ]. z* X9 Z4 g- Y  ]2 ^   Test():mCount(0)" k+ L* ?) g! e: q
   {* T' f* L. ^/ I# E, s
     mCount++;
/ J8 G6 @8 g" `" i/ {   }; M) Q5 j2 G, r6 p7 P+ g1 {# N* O
   ~Test()# T( c! N) _8 T$ Z2 s
   {# o) W: B: e  s5 y& W3 \& X
    --mCount;4 Y) A4 d5 }$ r4 y! B  O' [
   }
9 }9 L+ i! F. F. }   int getCount()
0 z& T6 p: b& P2 w* ]- j7 s9 q   {" ~+ l. z3 S% |0 G7 X) ~$ N3 |
       return mCount;
" N% F( Z2 t" W8 g+ M2 u' c; f+ C" Z% V* _
   }
4 e- T, s" O5 E* [2 v" R/ A& f};' s  k8 a! k. ]
Test gTest;2 ^& `1 A! ~0 D4 W
int main()
; B6 c3 m2 w& P8 M/ z! {* ]{( n! @# y: U$ i6 {
    Test t1;
) R* x; w0 ^* X1 d    Test t2;
) r2 F# h" M8 q. _/ z, h# H
' X& a. S8 Y) `3 \1 O' }    printf("mCount = %d\n",gTest.getCount());
3 m! E5 \( n+ \    printf("mCount = %d\n",t1.getCount());
; k4 W7 n5 V5 I1 Q4 r/ |+ r3 A    printf("mCount = %d\n",t2.getCount());( E) Y# D2 {' N

1 C% t0 e" k. @/ P    return 0;
/ p7 H1 o$ T- {$ e! {+ }) V}$ K& y. {/ w& l. {8 n

  h, K* D3 ?' Q: z9 y/ F8 @
运行结果:
root@txp-virtual-machine:/home/txp# ./a.out
: W* [0 ?3 q& Y8 ^/ @mCount = 1, [8 i$ s0 E2 M2 H4 |
mCount = 1) O  o7 \( i6 j9 S% Z7 E
mCount = 1
: |( v) p" y, N

  \5 I: [$ M3 R% E, h( G9 D* ^
从运行结果来我们可以看出来,对象独立性(专属性);而且结果没有达到我们的预期要求,于是乎,为了解决这个问题,我们就要排静态成员变量出场了。
1、c++中可以定义静态成员变量:
  • 静态成员变量属于整个类所有
  • 静态成员变量的生命期不依赖于任何对象(上面的程序,每个对象的成员变量是独立的,所以打印出的mCount的值分别为1)
  • 可以通过类名直接访问公有静态成员变量
  • 所有对象共享类的静态成员变量
  • 可以通过对象名 访问公有静态成员变量

    . I& P0 g  f- \) {  ?
2、静态成员变量的特性:
  • 在定义时直接通过static关键字修饰
  • 静态成员变量需要在类外单独分配空间
  • 静态成员变量在程序内部位于全局数据区
    ' B% K) x5 L& O/ F4 ~
3、语法规则:
Type ClassName::VarName = value;
& P" C0 J& g5 u" M* _; }9 D" b% S+ A# R; k
注意在类的外部进行初始化

  r" Q* o7 `0 e; W( R
代码版本二:
#include <stdio.h>; T/ b2 B+ k! h' Z; D) {3 c
class Test* X7 e& G$ s0 c
{
* _" ~! \4 h  m9 P( Y# kprivate:
$ p. P; O+ V' m1 a  static int mCount;
, u0 R; k1 R9 D( p0 U6 L- I$ Cpublic:; A3 W) \" u" ?% L. w
  Test()//不要使用初始化列表进行初始化
8 V7 @1 U3 j2 Q4 p2 H1 ~) l. X6 H  {
7 k- x- s$ ^* q2 y    mCount++;* g* P1 E/ \5 T- G( J" o
  }- r/ ^  w" d# O! z
  ~Test()
7 k" i8 C4 w0 D0 i/ p  t  {
3 [. p* k/ l4 D& R0 {6 c     --mCount;1 q( x; M6 x* D4 l
  }
( i! _/ Y" k" ^% v  int getCount()6 t" Y) |4 s( d! v0 g
  {
8 ?# o$ M1 T) D3 _1 q5 C      return mCount;: R" |; d0 Z5 T3 C) M6 ~
  }
2 R1 _% m% U3 Q7 m: }( f' I};
% D$ w9 k8 j+ M5 Q; D% {3 E6 tint Test::mCount = 0;; C6 E0 T8 t6 k8 f" A  ?
Test gTest;# l! {4 F' a# u
int main()
: l' N+ s* J) y. r4 o1 u& G, X8 K{/ w7 h4 J% Z  J
   Test t1;
4 d6 p2 D' R- y   Test t2;4 T& _* d) _5 v8 {# i) p' [  P

! p/ C% f" o9 z: z' D   printf("mCount=%d\n",gTest.getCount());2 l0 N: G. J! g1 [+ P2 ~
   printf("mCount=%d\n",t1.getCount());
8 Y0 V( Z# f9 n* U   printf("mCount=%d\n",t2.getCount());
! u9 f" w: m* j$ D; H0 \
0 `4 O1 z7 {4 e7 M/ T   return 0;- w5 Y# O3 g2 K
}
! f# |& P! |8 u* x4 C4 D! K
; \- f) S2 h! w7 `+ {4 m0 u
运行结果:
root@txp-virtual-machine:/home/txp# ./a.out5 ?0 b: h- Q3 u) z5 l
mCount=3
! {3 r. S7 j; l3 m. P  Q# ?) xmCount=3( O0 e/ r4 c; r7 a
mCount=3, l/ `+ k2 l+ ]7 C
( i8 Z7 s3 T7 A) U
说明,这里静态成员变量不能使用初始化列表去初始化,这里要明白上面说的那句话:静态成员变量需要在类外单独分配空间,换句话说,就是只有在类的外部重新定义静态成员变量才可以存储到静态存储区。报错如下:
root@txp-virtual-machine:/home/txp# g++ test4.cpp
% O: l! ?" R+ U' d8 c1 P# J. Btest4.cpp: In constructor ‘Test::Test()’:. ?8 p) u/ s9 E  o) j
test4.cpp:7:10: error: ‘int Test::mCount’ is a static data member; it can only be initialized at its definition  w9 |; `6 w& k' S) V1 a' u
   Test():mCount(0): v1 n/ S) L0 s) E; ^
% M0 q( e) y7 K. G
4、小结:
  • 类中可以通过static关键字定义静态成员变量
  • 静态成员变量隶属于类所有
  • 每个对象都可以访问静态成员变量
  • 静态成员变量在全局数据区分配空间
  • 静态成员变量的生命期是在程序运行期间
    ! H0 x4 E! V' t  X( ?6 T/ m
二、静态成员函数:
刚刚程序版本二里面其实我们还有一个功能没实现完:随时可以获取当前对象的数目。所以我们还要想办法来实现,下面是代码版本三:
#include <stdio.h>" n) j. y6 f, j" |

7 Z* P( |5 v" }& mclass Test6 `$ G* L0 ]8 r% g5 v6 M4 ?6 C: x
{$ [7 @! J7 I( ]9 W+ Y5 Y1 u# N
public:
& N8 a9 ^$ O8 C5 ?2 V    static int mCount;
! R- \- q7 a  R) v% A2 rpublic:7 R2 R: B4 g+ }1 g/ v% o/ N4 V0 O
    Test()
7 A$ I$ u+ @: s% P5 _( o: S    {5 s+ r. P; c; j2 M# g7 R6 }
        mCount++;1 i' q. i* U8 R! u
    }
- S/ w# N  v0 q3 ^0 D    ~Test()& K! d# r# q5 j% h4 [' p( x8 e
    {* R. J% u6 d1 a: i8 V. z1 {
        --mCount;- x% c+ j. `) v. f. _
    }
4 y1 `% A# n, h# y    int getCount()) r0 {$ {; _4 i$ G6 S$ U: P
    {
4 X, S& z5 y  @2 T1 a# z; v$ p        return mCount;- B5 b+ S: q8 o& y/ Q
    }9 D. a* x& L/ H- N; d$ o$ j
};
; O7 \# Q# [4 x7 g9 H
+ A+ n1 v! e9 k" X2 Yint Test::mCount = 0;
) ~3 l5 l4 r4 h1 F( Z. r5 u; q/ H% Y8 Z9 k2 ^4 K

0 x9 X: f/ n6 E# S. J6 ?7 x$ wint main()% s" s6 u& ?1 c8 }
{( I& }! f7 I  {' Y3 f
    printf("mCount = %d\n", Test::mCount);
; `1 P4 O8 T8 E0 h7 M. h& n    . _6 t8 T6 C0 C+ \
    Test::mCount = 1000;
8 i) N0 q$ j) J   
1 ?' T8 H. T( T+ y2 c' Q* m% p    printf("mCount = %d\n", Test::mCount);
$ R2 v7 I5 ?' Y4 D4 J   
! o% ~+ Z' a! K4 I    return 0;+ q6 R2 E5 S! S, A
}, z% ]) ?* v% E' F1 f

# k3 S6 X4 C4 s
运行结果:
mCount = 0
9 d& Y1 R/ A1 t; zmCount = 1000* C) {7 h5 ?" H6 b. o" g
* L$ ?) q6 R4 ^7 J. ]6 `
这里用类名来访问静态成员变量,但是不安全,比如说这里给mCount赋值1000,你能说有一千个对象嘛,再说我们也没有去手动创建对象,所以还是不符合要求;为此这里我们又要引出一个新的概念——静态成员函数。
1、在C++中可以定义静态成员函数:
  • 静态成员函数是类中特殊的成员函数
  • 静态成员函数属于整个类所有
  • 可以通过类名直接访问公有静态成员函数
  • 可以通过对象名访问公有静态成员函数
    4 K5 _. c& c, k
2、静态成员函数的定义:
直接通过static关键字修饰成员函数:
class Test
$ R0 e# f3 ]" M) {- t{
2 N4 m* ?0 Z6 N% ^/ Q: a% rpublic:8 c; Z+ a* E8 |3 k2 v3 l$ l" M
  static void Func1()
. ?4 r) c6 Q  i  {}+ X3 w  ^  }% q5 I9 m
  static int Func2();
3 g# Y: {: G0 _9 g
& R" ?) {0 I6 L/ B
0 }8 }1 `! u1 U1 ~}
- v) `: K5 ^! V1 m! Y8 L
静态成员函数代码演示:
#include <stdio.h>
" F2 `) U9 d- _- X6 b% F1 b' ~7 ^* D
( i, B6 e+ \2 cclass Demo0 r# A0 F/ T1 J
{
/ g4 V$ e4 h% @. k( \" R1 Kprivate:6 e% s+ `0 I3 G: ^; ^" n" q
    int i;
. s5 z% E+ T# z/ K6 X6 R# vpublic:
- p9 V9 Z# m" T- U; v# L3 d9 ^4 d$ v    int getI();+ M+ _5 T  H: j/ o6 I! a6 u1 c( M
    static void StaticFunc(const char* s);
* [# Q; e  G; f8 n/ ]    static void StaticSetI(Demo& d, int v);
6 o; @" S7 w: S" T+ J! I};
9 y) g  q, ~: ?% _* D
; |; f% i3 Q( ]- Wint Demo::getI()3 \8 x9 }# o3 [" s3 b* J
{
1 K& ?& E2 m! I) q. ^1 Q/ T  ]    return i;
6 t& Q2 n; S3 D; M' l2 ^}2 W! h# y' }$ d2 j" \$ Y4 G

. ^9 V# H: W1 Z  N/ J2 E% Qvoid Demo::StaticFunc(const char* s)  X+ R: C4 b) n! e  d! W
{
' t$ u1 r* b4 T, f    printf("StaticFunc: %s\n", s);
2 I6 u' ^  O! Z/ _}) h7 t* M- C' k5 H4 z  A

8 D6 _* N( p; P) m: r6 w' {void Demo::StaticSetI(Demo& d, int v): B) b$ R3 O& a
{* b4 X- K5 x5 o7 R
    d.i = v;4 j) }5 P5 ]: c$ M, H
}& w+ p: D( P5 o/ i

$ U# G1 A6 J, V5 r9 h8 M; B+ `. vint main()3 T& w& K/ e. C
{
$ Z/ W5 v- Y; c% F; K3 s2 H, {    Demo::StaticFunc("main Begin...");9 g. R/ ^4 K' t# V% h6 B) d% w/ l( u
   
4 A+ ]6 [+ U4 Z( m0 V! d    Demo d;: C! \9 x5 O* ]6 g7 G; J" B. k; z# k9 C- A
   
7 z8 {* }& [* c& {! O( y    Demo::StaticSetI(d, 10);
9 H+ p, [" ?+ _' G) I; [* ^    . G0 r9 |7 f( C+ E' e5 Z
    printf("d.i = %d\n", d.getI());
( @& N* K9 n( m9 |   
! D3 [& Q7 y6 D    Demo::StaticFunc("main End...");
; |; N% y) R3 u4 V. A   
$ ^7 {; z7 n. b! @: |    return 0;5 {) F8 H0 F6 l. l' u
}
0 G- v% H! F5 K) m8 J& M1 {

( M' M+ }4 ^+ t: I, @8 S
结果输出:
root@txp-virtual-machine:/home/txp# ./a.out; ]* z* t9 b4 u- G  V; y# @
StaticFunc: main Begin...5 s1 p# q/ V& L
d.i = 10  P2 Q* {# w% Y- p# v
StaticFunc: main End...
2 ~+ p8 K6 D3 w: j% J9 |
/ E, ^$ `: w- e2 B+ A
3、静态成员函数 vs  普通成员函:
静态成员函数
普通成员函数

4 b1 j" ]) a3 t( O& {  V  Y' S所有对象共享YesYes) ^( C6 K, F0 a& V  i6 k
隐含this指针NoYes  [  J' {  Y+ M1 o. y: ?
访问普通成员变量(函数)NoYes% m2 Y: g: v; {& _
访问静态成员变量(函数)YesYes" E& x! m' @; o
通过类名直接调用YesNo" c; J5 j6 x: W0 o$ D- Y. t
通过对象名直接调用YesYes
4、版本代码四:
#include <stdio.h>% Z" f$ O2 P6 [$ _/ c8 i4 V
. _5 q% _- J8 h/ }* s
class Test2 l, B& U" }' K' L: S6 u9 l
{
7 E) V. R% r  R, q! s+ X, tprivate:
" N; H- n6 D* K$ `5 i; Q* Y    static int mCount;
3 H. I# S* B9 y, Gpublic:
7 e6 C, a4 Q1 g& `) p    Test(), M7 Y- [8 `( h: n" p5 F
    {4 x% N9 U& z# X# c0 u: n+ o
        mCount++;
# s7 b# y1 [8 H/ ?3 Z    }1 \$ F, {+ O4 P
    ~Test()2 O% U) v  ]" d1 j  P+ j
    {) x7 [4 B2 a8 e- h
        --mCount;3 t1 Z1 S& ^4 C+ Y% n$ e+ O
    }
# c& M. X/ ^, w( j9 Y1 p4 _  v    static int GetCount(), k! C. s: F# W4 p
    {5 Q& b: B% v$ L1 M2 K/ n
        return mCount;' q( {, `- l1 c* M  a
    }
7 ^0 W+ Z% g0 e. M' f, u7 B};/ a% e5 B; ]& @; Z3 d/ G- J

7 l0 O( Z- \5 k! L+ o) N. Y: \2 H& ^9 Rint Test::mCount = 0;# j6 S" ?: q; I/ p

4 j! s, `3 k. A: b9 gint main()5 l' S1 Y, F6 e8 w$ }0 y" {1 }
{
& {  h4 A* I9 m/ T    printf("mCount = %d\n", Test::GetCount());% D$ ]7 f8 Q, _+ O
   
/ X, m$ b& u5 Q4 o7 l# Q3 u5 H    Test t1;' v! K( }/ `2 E' U1 ^6 [7 H
    Test t2;
$ h6 X! v' L+ G9 m( [   
# {. i" m* `8 G; m8 f    printf("mCount = %d\n", t1.GetCount());
1 n: L+ B# v3 R    printf("mCount= %d\n", t2.GetCount());
+ X8 o- l) ]8 b6 E    + ]1 S: e0 N  V9 J1 Y3 u
   
( v1 z& L7 K0 K# L   
- D  i9 v# O" g) X) i- Z; F    return 0;
" M$ X  H8 R5 E+ B3 r}
, D, ~1 t. E8 }$ F- b

6 i' N* x) n6 ~' X2 H* h
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out& n' G# b$ w) b% a7 r5 G) `% K3 H
mCount = 0
1 q9 P  m6 T/ ^+ m- N' c+ omCount = 2' P" j9 s1 c; `( p% v
mCount= 2

+ _% A& t: q/ g" @
通过输出结果,我们可以看出,实现了第三个功能:随时可以获取当前对象的数目。
4、小结:
  • 静态成员函数是类中特殊的成员函数
  • 静态成员函数没有隐藏的this参数
  • 静态成员函数可以通过类名直接访问
  • 静态成员函只能直接访问静态成员变量(函数)

    % z5 u# E* R. S# e/ q* U4 k" o
三、总结:
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。
- Q, a7 M: [9 U- A8 e
赞 收藏 1 评论0 发布时间:2020-8-9 21:02

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版