这篇文章归类到了c++中是因为第一次学习static是在c++中,但实际上真正较好地理解它却是在最近看的Java中。
static本身的中文解释为“静态的”,这与咱们的编程语言中的含义是一样的。通俗来说,只要变量/方法用static修饰了,它“已经静静地在那里存在了”。
具体来看例子更好理解,用c++的语法来写:
1.static变量
int i;
static int j;
相当简单的两行代码,第一行定义了一个整型变量i,但没有对它进行初始化,因此它的值将是不确定的。
第二行同样定义了一个整型变量j,同样也没有初始化,但用static关键字进行了修饰。这样一来即使我没有对j初始化,j也有了默认值0。
不相信的同学可以cout验证一下。
这里说明了第一个事:static修饰的变量具有默认初始值0(当然这不仅限于int类型,double/float/char等等基本类型都一样,同样我们可以进行验证)。
接下来看下面的代码
void my_method()
{
int k=0;
static int m;
}
int main()
{
my_method();
m++;
cout<<m<<endl;
//cout<<k<<endl;
retrun 0;
}
这段代码如果去掉倒数第三行的注释符号(即加上cout<<k<<endl;这句)一定是编译不过的,因为我们都知道k是一个局部变量,它的生存期随my_method()函数结束而结束。
但static变量就不一样了:即使变量所在的函数运行结束,变量依然存在并保持它的当前值,并且可以继续在后续代码中使用。这就是static修饰变量的第二个用法。
回头看在文章开头的那个说法,顺带总结一下static变量:
只要变量/方法用static修饰了,它“已经静静地在那里存在了”——这意味着static变量在未初始化时有默认值0,且一直存在,在程序运行过程中不会因为函数结束而消失。
2.static方法(函数)和存在于类中的static
在一块儿我认为大家应该用面向对象的思维来理解,一方面是因为下面的代码要写类(class)了,但不会很复杂。另一方面,或许比较敏感的同学发现了文章开头的那种通俗说法“只要变量/方法用static修饰了”这半句没有包括对象。这么做有两方面原因:第一是我个人在没接触Java时认为对象也是个变量,只不过比较特殊而已(当然现在我已经改变了这个错误的想法,《Java编程思想》(《Think in Java》为英文原著)让我明白了创建一个对象实际上是创建了它的一个“引用”(更准确来说更像是指针));第二是我认为对象是和类分不开的,因为至今还没看见过static class这种用法。
说了这么多,还是来看下面的代码:
class my_class
{
private:
static int i;
public:
void my_method(){i++;}
static void my_s_method(){i++;}
void show(){cout<<i<<endl;}
};
类声明过后在主函数做一些操作:
int main()
{
my_class.my_s_method();
my_class a;
a.show();
return 0;
}
运行结果将是
1仔细看,我们做了这么一个工作:直接通过类名调用类之中的静态方法(函数)而没有定义对象。对于类中静态的方法,这么做完全没问题,但对非静态的方法则是错误的。
同样的,对静态变量我们也可以通过类名访问。即
my_class.i++到此为止,static很经典的用法基本上就讲完了。斗胆引用《Java编程思想》(《Think in Java》为英文原著)中的一段话做个全面性的理解,同时也为这篇文章作结:
尽管当static作用于某个字段时,肯定会改变数据创建的方式(因为一个static字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象有一个存储空间),但是如果static作用于某个方法,差别却没有那么大。static方法的一个重要用法就是在不创建任何对象的前提下就可以调用它。正如我们将会看到的一样,这一点对定义main()方法很重要,这个方法是运行一个应用时的入口点。
和其他方法一样,static方法可以创建或使用与其类型相同的被命名对象,因此,static方法常常拿来做“牧羊人”的角色,负责看护与其隶属同一类型的实例群。