一、C++类的静态成员
学过C++的都知道,静态成员是属于整个类而不是某个对象的,静态成员变量在内存中只存储一份共所有对象共用,在所有对象中都可以共享它。
静态成员的定义或声明需要加个关键字 static。因为属于整个类,所以可以通过 <类名>::<静态成员名>来使用。
需要注意的是:静态成员属于整个类,在类对象实例化前,静态成员就已经分配空间了,而非静态成员无需初始化,必须在类实例化对象后才有内存空间,所以就有了个先后顺序:静态成员先于非静态成员存在。
1、通过类名调用静态成员函数和非静态成员函数
class Base { public: void fun1() { } static void fun2() { } }; int main() { Base::fun1(); Base::fun2(); return 0; }
编译错误:“Base::fun1”: 非静态成员函数的非法调用
结论1:不能通过类名来调用类的非静态成员函数。
原因:类没有实例化对象,非静态成员函数不存在
2、通过类的对象静态成员函数和非静态成员函数
class Base { public: void fun1() { } static void fun2() { } }; int main() { Base obj; obj.fun1(); obj.fun2(); return 0; }编译通过
3、在类的静态成员函数中使用类的非静态成员
class Base { public: void fun1() { } static void fun2() { cout << x << endl; } private: int x; }; int main() { Base obj; obj.fun2(); return 0; }编译出错:对非静态成员“Base::x”的非法引用
4、在类的非静态成员函数中使用类的静态成员
class Base { public: void fun1() { fun2(); } static void fun2() { } }; int main() { Base obj; obj.fun1(); return 0; }编译通过
5、使用类的静态成员变量
class Base { public: void fun1() { } static void fun2() { } static int x; }; //int Base::x = 0; int main() { cout << Base::x << endl; return 0; }链接出错:无法解析的外部符号 "private: static int Base::x" (?x@Base@@0HA)
但是,静态成员也并非不能再类中初始化。对于静态常量成员是可以在类中初始化的。
总结:
1.静态成员存在于内存,非静态成员需要实例化才会分配内存
2.非静态成员的生存期取决于该类的生存期,而静态成员则不存在生存期的概念
3.类的静态成员函数不能调用非静态成员,存在的先后顺序,反之可以
4.类的静态成员变量必须初始化,且必须在类外初始化(静态常量成员除外),不能带static关键字,必须带类型。
二、C语言中的static
下面介绍在C语言中,static的作用:
1、隐藏
当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。比如,同时编译两个源文件,一个是a.c,另一个是main.c
//a.c char a = 'A'; void msg() { printf("Hello\n"); } //main.c int main() { extern char a; printf("%c", a); (void)msg(); return 0; } //output:A Hello由于a.c 中的所有成员(变量和函数)都未加static,所有都具有全局可见性,其他的源文件也能访问。如果加了static,那么其余源文件就不能访问了,利用这一特性,可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。
2、static还能保持变量内容的持久
对于函数而言,static的作用仅限于隐藏,对于变量,static还有两个作用,其一就是保持变量内容的持久。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化,事实上,全局变量和静态变量都存储在静态存储区。与全局变量不同的是,static可以控制变量的可见范围。
int fun() { static int count = 10;//事实上此赋值语句从来没执行过,调试一进入函数,count=10 return count--; }