|
不知不觉,又到周末了;上次在交流群里,答应给大家免费送开发板,一开始认为板子够送,但是昨天整理了一下,然后送了大概十几个网友就不够送了,还有十几个网友没得到板子,这里说声实在抱歉,下次有机会搞活动再送给大家好玩的板子:
上图的板子有最近买的,也有以前买的(stm32、esp8266、51、esp32、小熊派、合宙的cat1、树莓派3b+);说实话,这些板子买来,一直放在那里吃灰,后期自己的方向也不玩硬件开发板啥的;所以上面的板子都送给了公众号读者在校生,让这些板子发挥它们最大的价值,板子也会在最近慢慢一一送出去;赠人与玫瑰,手有余香! 好了回归主题,今天继续分享c++的文章,学习还是不能落下,flag未完成,任务艰巨,好好学习。 一、静态成员变量: 平时我们在写类的时候,类中的成员变量,我们一般是通过对象名来访问public成员变量的,一般private(私有)的成员变量,对象是不能直接访问的;同时我们要明白每个对象的成员变量都是专属的,而且成员变量是不能在对象之间共享的,这就是专属性。下面我们来做一个小的程序需求来慢慢引出静态成员变量:
代码版本一: #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: Test():mCount(0)" k+ L* ?) g! e: q {* T' f* L. ^/ I# E, s mCount++; }; 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' [ } int getCount() {" ~+ l. z3 S% |0 G7 X) ~$ N3 | return mCount; + M2 u' c; f+ C" Z% V* _ } };' s k8 a! k. ] Test gTest;2 ^& `1 A! ~0 D4 W int main() {( n! @# y: U$ i6 { Test t1; Test t2; printf("mCount = %d\n",gTest.getCount()); printf("mCount = %d\n",t1.getCount()); printf("mCount = %d\n",t2.getCount());( E) Y# D2 {' N return 0; }$ K& y. {/ w& l. {8 n 运行结果: root@txp-virtual-machine:/home/txp# ./a.outmCount = 1, [8 i$ s0 E2 M2 H4 | mCount = 1) O o7 \( i6 j9 S% Z7 E mCount = 1 从运行结果来我们可以看出来,对象独立性(专属性);而且结果没有达到我们的预期要求,于是乎,为了解决这个问题,我们就要排静态成员变量出场了。 1、c++中可以定义静态成员变量:
2、静态成员变量的特性:
3、语法规则: Type ClassName::VarName = value;" b% S+ A# R; k 注意在类的外部进行初始化 代码版本二: #include <stdio.h>; T/ b2 B+ k! h' Z; D) {3 cclass Test* X7 e& G$ s0 c { private: static int mCount; public:; A3 W) \" u" ?% L. w Test()//不要使用初始化列表进行初始化 { mCount++;* g* P1 E/ \5 T- G( J" o }- r/ ^ w" d# O! z ~Test() { --mCount;1 q( x; M6 x* D4 l } int getCount()6 t" Y) |4 s( d! v0 g { return mCount;: R" |; d0 Z5 T3 C) M6 ~ } }; int Test::mCount = 0;; C6 E0 T8 t6 k8 f" A ? Test gTest;# l! {4 F' a# u int main() {/ w7 h4 J% Z J Test t1; Test t2;4 T& _* d) _5 v8 {# i) p' [ P printf("mCount=%d\n",gTest.getCount());2 l0 N: G. J! g1 [+ P2 ~ printf("mCount=%d\n",t1.getCount()); printf("mCount=%d\n",t2.getCount()); return 0;- w5 Y# O3 g2 K } ; \- f) S2 h! w7 `+ {4 m0 u 运行结果: root@txp-virtual-machine:/home/txp# ./a.out5 ?0 b: h- Q3 u) z5 lmCount=3 mCount=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.cpptest4.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、小结:
二、静态成员函数: 刚刚程序版本二里面其实我们还有一个功能没实现完:随时可以获取当前对象的数目。所以我们还要想办法来实现,下面是代码版本三: #include <stdio.h>" n) j. y6 f, j" |class Test6 `$ G* L0 ]8 r% g5 v6 M4 ?6 C: x {$ [7 @! J7 I( ]9 W+ Y5 Y1 u# N public: static int mCount; public:7 R2 R: B4 g+ }1 g/ v% o/ N4 V0 O Test() {5 s+ r. P; c; j2 M# g7 R6 } mCount++;1 i' q. i* U8 R! u } ~Test()& K! d# r# q5 j% h4 [' p( x8 e {* R. J% u6 d1 a: i8 V. z1 { --mCount;- x% c+ j. `) v. f. _ } int getCount()) r0 {$ {; _4 i$ G6 S$ U: P { return mCount;- B5 b+ S: q8 o& y/ Q }9 D. a* x& L/ H- N; d$ o$ j }; int Test::mCount = 0; ; q/ H% Y8 Z9 k2 ^4 K int main()% s" s6 u& ?1 c8 } {( I& }! f7 I {' Y3 f printf("mCount = %d\n", Test::mCount); . _6 t8 T6 C0 C+ \ Test::mCount = 1000; printf("mCount = %d\n", Test::mCount); return 0;+ q6 R2 E5 S! S, A }, z% ]) ?* v% E' F1 f 运行结果: mCount = 0mCount = 1000* C) {7 h5 ?" H6 b. o" g * L$ ?) q6 R4 ^7 J. ]6 ` 这里用类名来访问静态成员变量,但是不安全,比如说这里给mCount赋值1000,你能说有一千个对象嘛,再说我们也没有去手动创建对象,所以还是不符合要求;为此这里我们又要引出一个新的概念——静态成员函数。 1、在C++中可以定义静态成员函数:
2、静态成员函数的定义: 直接通过static关键字修饰成员函数: class Test{ public:8 c; Z+ a* E8 |3 k2 v3 l$ l" M static void Func1() {}+ X3 w ^ }% q5 I9 m static int Func2(); }- v) `: K5 ^! V1 m! Y8 L 静态成员函数代码演示: #include <stdio.h>class Demo0 r# A0 F/ T1 J { private:6 e% s+ `0 I3 G: ^; ^" n" q int i; public: int getI();+ M+ _5 T H: j/ o6 I! a6 u1 c( M static void StaticFunc(const char* s); static void StaticSetI(Demo& d, int v); }; int Demo::getI()3 \8 x9 }# o3 [" s3 b* J { return i; }2 W! h# y' }$ d2 j" \$ Y4 G void Demo::StaticFunc(const char* s) X+ R: C4 b) n! e d! W { printf("StaticFunc: %s\n", s); }) h7 t* M- C' k5 H4 z A 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 int main()3 T& w& K/ e. C { Demo::StaticFunc("main Begin...");9 g. R/ ^4 K' t# V% h6 B) d% w/ l( u Demo d;: C! \9 x5 O* ]6 g7 G; J" B. k; z# k9 C- A Demo::StaticSetI(d, 10); . G0 r9 |7 f( C+ E' e5 Z printf("d.i = %d\n", d.getI()); Demo::StaticFunc("main End..."); return 0;5 {) F8 H0 F6 l. l' u } 结果输出: 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... / E, ^$ `: w- e2 B+ A 3、静态成员函数 vs 普通成员函: 静态成员函数 普通成员函数 所有对象共享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 { private: static int mCount; public: Test(), M7 Y- [8 `( h: n" p5 F {4 x% N9 U& z# X# c0 u: n+ o mCount++; }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 } 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 } };/ a% e5 B; ]& @; Z3 d/ G- J int Test::mCount = 0;# j6 S" ?: q; I/ p int main()5 l' S1 Y, F6 e8 w$ }0 y" {1 } { printf("mCount = %d\n", Test::GetCount());% D$ ]7 f8 Q, _+ O Test t1;' v! K( }/ `2 E' U1 ^6 [7 H Test t2; printf("mCount = %d\n", t1.GetCount()); printf("mCount= %d\n", t2.GetCount()); + ]1 S: e0 N V9 J1 Y3 u return 0; } 输出结果: root@txp-virtual-machine:/home/txp# ./a.out& n' G# b$ w) b% a7 r5 G) `% K3 HmCount = 0 mCount = 2' P" j9 s1 c; `( p% v mCount= 2 通过输出结果,我们可以看出,实现了第三个功能:随时可以获取当前对象的数目。 4、小结:
三、总结: 好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。 - Q, a7 M: [9 U- A8 e |
微信公众号
手机版