类内静态函数和全局静态函数的相同点和不同点
上一篇 / 下一篇 2012-08-14 11:01:50 / 个人分类:杂谈
2)类静态函数,对比普通成员函数,没有this指针,不能访问非static成员。51Testing软件测试网 P4Mt J t)ns
51Testing软件测试网RHd*L)KZ#?%t.vq3)要说二者相同点,都是c++名字控制的手段:全局静态函数被局限在一个编译单元,通俗的将就是在一个cpp文件中定义的全局静态函数在另一个cpp文件中不能被调用。例程如下;51Testing软件测试网1G Ug:aO7OT
51Testing软件测试网&? r)I;TS;cS)@ c51Testing软件测试网 r/['\~%}lXW2kNi
// main.cpp51Testing软件测试网]EQ}&C
n*dE #include <iostream> :a&\lY3m}n\0extern int hello2();51Testing软件测试网@.pY$j f static int hello()51Testing软件测试网%~kO%KH/i {51Testing软件测试网9[.?FSs0f8p$l std::cout < < "hello, world! " < < std::endl; Re_?-] o x;i-b0 return 0; :_ Bi5^ o0} }+WrC'U ]0int main() .b K4B/]Q^0{51Testing软件测试网0~AKt3|? hello(); 3xR@ZW0 hello2();51Testing软件测试网 a1d1R1h`u~ }51Testing软件测试网.z(s9l1G X:^2R // append.cpp51Testing软件测试网 [ v5gz'o Sp extern int hello();51Testing软件测试网9oR&F7H6t![6f9yf int hello2() _'E{!f:o1O y0{51Testing软件测试网t9tYW3J YX6b hello(); "uHW{ uF?y,N0}51Testing软件测试网o3d&cy0vf};w //--------------------------------------------- |
编译将产生错误:
,^%ekmHH AM0w1je$Hc"hF0 append.obj : error LNK2001: unresolved external symbol "int __cdecl hello(void) " (?hello@@YAHXZ)
}9f/U$D gE\0 Debug/Test.exe : fatal error LNK1120: 1 unresolved externals51Testing软件测试网'PG-S i9kvu8I
而把hello前面的static去掉之后就可以编译成功了。51Testing软件测试网'C/W"h3X&J(try _dp
E+z.V"NK|4o0 可见不能在append.cpp中调用main.cpp中的全局静态成员函数。
#W"gcy_0^ Z)jVODOR0 而类静态函数,必须使用其“类名::静态函数名”51Testing软件测试网)s*N.}2Y{e1Yo3HE
51Testing软件测试网Rq/s}8z }C~*?6DW:k @P7AQ#zN [0#include<iostream> *M7T"g'F!dLv c0using namespace std; "krTqJ;Z c0class A51Testing软件测试网x3|7Kj$@2O:{I2? { A-q y*MkEZ%u*Ra0 public: u9G{ WeuK0 static void fun(int x) Q;t9OpFO0]3\RB0 {51Testing软件测试网AfwJx0pf2A E)C 51Testing软件测试网v0Bk~N|1k%b cout<<x<<endl;51Testing软件测试网xDmf_9o } ^ {A ^(K(i:fO0}; ScztgI0int main() Bp`N f,]Vo0{ J qN4Io4Y;^0 A son; -YqMge6k3[0 son.fun(5);51Testing软件测试网(d/E0N*u1A0|#yEJ-a-p // A::fun(5); hc3b]H wt?|0 return 0; L6K6q-Lqs0} |
编译虽然会出结果,但是有一条警告,son未引用的局部变量,说明静态成员函数不可以用对象调用的。但是至于为什么会输出正确结果不太理解,望高手指教。也有待进一步研究。用//注释起来的也可以输出正确结果。
~{5oD|n4N"uAy0n051Testing软件测试网 C1kNi u%Wq|我们把函数和变量声明为静态的有什么优点那,从静态变量的角度看,更容易理解一些。51Testing软件测试网P)d7hCHd G;Y
51Testing软件测试网8`s0SV[.s使用静态数据成员可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值 对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,就可以保证所有对象都能够访问到被更新后的值,这样可以提高效率和节省内存 空间。这是静态变量的优点同时也是他的一个缺点,在类中声明了静态变量,无论用户使用使用这个类,而这个静态变量都会申请他需要的内存容量。对于多线程的 情况下,访问静态变量我们需要加一些异步机制,防止多个线程同时修改静态变量。
]T1k8[8B3f1vDJE0OGm5z ET8k6[+P0 类内静态函数比全局静态函数的用处要多的多,在这里先讲简单的51Testing软件测试网 q2r8]7{3Z)~
51Testing软件测试网6]&F[!j{ }f"i全局静态函数的应用比较常见的就是51Testing软件测试网-I"i9~;Ox[
ou5y*_9Xft051Testing软件测试网VO!z1{ a
static int fun() 1l4sIr8fY0{ OFPn$@8]%R'f0...;51Testing软件测试网;E,g'G8^,} Wk1J return 1; 6u ~4}$[2vS0} |
UoC9dx+j ^0 当我们希望在多个类中调用fun函数时,我们必须把fun声明为static类型,不然在link时编译器会发现多个关于fun的定义。这种函 数的应用,多少带有C的色彩,尤其当我们在C环境写好的函数,移植到C++中时,需要在函数前面需要加上static,而如果我们需要移植多个函数时,更 通用的一种方法是使用未命名名字空间51Testing软件测试网7dt(D$Q;| y;e-vG|
51Testing软件测试网@&AQYM"D_!}51Testing软件测试网3[g-Srj6@8`3\tK%S
namespace{51Testing软件测试网*g:A'Z
t@P!A.] int fun() *W$me5v'B4Gef0{ vO0B5R%qwK0...; &OPC~4_y w*A0return 1;51Testing软件测试网.]`f/r wSO }51Testing软件测试网SRx;@2v4ba2D i …51Testing软件测试网g$c(V8p9\!^_&J,w } |
G_ x.B?V0 也许有人问如果在未命名名字空间中的函数再加上static修饰符号会怎么样?这个就完全取决以使用的编译器,可能会直接报错,也可能可以编译并正常使用。不过这样写,代码从语言层次上就很难移植编译环境,所以尽量不要这样写。
@cR7M)UsH0c}C)^7V$?0 关于这样的应用,在我从前的项目中实施过。当时我需要定义很多函数,执行三角形,已经像素转换方面的计算,所以把这些函数声明为static的。51Testing软件测试网G+b|&`6|F
51Testing软件测试网#_BC r4Y[%s对于与全局静态函数,我们继续类内静态函数和静态变量的讨论,我想他们的应用是两者区别的最好体现。
6_"]M-ZkSY01Tkw{V1w0 对于类内静态变量,我们需要在类外初始化,这是在使用静态变量需要注意的地方,有些初学者很容易在这里出错。类内静态变量使用最多的就是计算类的实例化个数。51Testing软件测试网?M&Q*n ]L$@
51Testing软件测试网EF o0?T51Testing软件测试网 \Gz:Z*T&}
class A51Testing软件测试网w5n;~qYfH4M p)I {51Testing软件测试网L~T;od,|vG8z static int i; // 外部初始化为051Testing软件测试网%MrnLl^F public:51Testing软件测试网I x1i Iqk ] A() // 构造函数51Testing软件测试网-[:{!xH:_KZ {51Testing软件测试网a#S,T[8{t0m7z| ++i;51Testing软件测试网 Wy"\`'l~-Cv } \ D5RfV8B(o%~1f-z1K0~A() // 析构函数 2Wg:^.}G{x.o3fA0{51Testing软件测试网#h(~BK3~|&R tla --i; gd4[{0Zb1t,XS$T#F0} SReIJ!})FS9r-ruS.A0static int CreateObjectNumber() // 或者创建对象的数目 &Kh@uG6y"jL0{ UoRs7x%{m7y0return i; YAn%j-Ki0} |