static的用法主要分为两大类,一种是在c语言中的用法,还有就是c++在类中的用法。
1. 在C语言中
1.1 修饰全局变量
定义静态全局变量就是在全局变量前加上 static 关键字
#include <iostream>
static int a = 10; //这是静态全局变量
int main()
{
return 0;
}
静态全局数据的特点:
1、静态全局变量就在全局数据段分配内存。
2、静态数据如果不初始化会被自动初始化为0
3、静态全局变量在声明它的整个文件都是可见的,在其他文件中不可见,它和extern的作用相反
static 的第三个特点还有个好处,就是可以防止命名污染,不用担心在别的文件中重复定义一个变量。
1.2 修饰局部变量
static 修饰的局部变量就是静态局部变量。静态局部变量和静态全局变量的共同点就是都是在全局数据区分配内存的。
局部变量的特点:
1、在全局数据区分配内存
2、静态局部变量在声明时初始化,如果用户没初始化,那么初值也会被初始化为0
3、当程序执行到局部变量的声明位置时被首次初始化,后面的函数再调用时不会初始化
4、它的作用域是局部的,只作用于该函数中,但是它的生命周期已经变为随程序了。因为它在全局数据区分配,所以生命周期变为整个程序,但出了函数范围,作用域结束。
举个栗子:
#include <stdio.h>
int i = 1;
void fun()
{
static int n = 0;
printf("执行了 %d 次\n", i);
printf("n 的值:%d\n", n);
i++;
n++;
}
int main()
{
fun();
fun();
fun();
fun();
return 0;
}
看起来每次执行函数都有初始化语句,但是static的作用就是只是在第一次声明的时候初始化,后面再次调用函数的时候,变量不会被初始化,对于这个函数变量会随着函数的调用次数而改变,所以结果如下:
1.3 修饰函数
在函数的返回类型前面加上 static 关键字就是静态函数了。
静态函数和普通函数的最大区别就是静态函数只能被本文件可见,不能被别的文件调用。这样也可以防止函数命名冲突。
#include <stdlib.h>
static void fun() //静态函数
{
printf("执行了 %d 次\n", i);
i++;
}
int main()
{
fun();
return 0;
}
2. 在C++中
在 C++ 中,和C语言中不同的是C++对类成员进行的修饰。
声明为 static 的类成员就是类的静态成员,分别是静态成员变量和静态成员函数。
static修饰的成员变量就是静态成员变量;
static修饰的成员函数就是静态成员函数。
2.1 修饰类中成员变量
class Test
{
private:
static int _count;
};
int Test::_count = 0; //类外初始化
int main()
{
Test::_count; //没有创建对象也可以访问
return 0;
}
类中的静态成员变量一定要在类外初始化,在类内直接初始化会报错;
为什么在类内初始化会报错?
答:因为程序中如果没有创建对象的话,定义类的代码是不会生成的。所以我们对一个不存在的东西赋值当然会报错!!
静态成员变量的特点:
1、类中静态成员为所有类对象所共享,不属于某个具体的实例,即静态成员变量只分配一次内存,供所有对象公用;
2、类中静态成员变量必须在类外定义,定义时不加 static 关键字;
3、类中静态成员变量的访问是通过【类名::静态成员变量】或【对象.静态成员变量】的方式来访问
4、类中静态成员变量也遵循 public、protected、private 的访问权限,以及 const 修饰符等;
5、类中静态成员变量是在全局数据区分配内存,不属于某一个类对象,而是属于本类所有的类对象,所以即便没有实例化对象,也可以通过【类名::静态成员变量】的方式访问.
6、应用场景:可以用于多个类具有相同的属性时,当所有类的这个属性都要更改时,那么只需要更改一处即可,而且静态成员变量只在全局数据区存储一份,更省空间。
静态成员变量和全局数据比较:
静态成员变量可以是private属性,而全局变量不可以,所以全局变量一定程度破坏了封装。
静态成员变量也可以减少命名冲突。
2.2 修饰类中成员函数
静态成员函数的特性:
1、类中静态成员函数的访问是通过【类名::静态成员变量】或【对象.静态成员变量】的方式来访问
2、类中静态成员函数也遵循 public、protected、private 的访问权限,也可以具有返回值以及 const 修饰符等;
3、类中静态成员函数中没有 this 指针,所以不能访问非静态成员函数,就因为它不是属于任何一个对象,所以没有this指针;
4、没有this指针,静态成员函数与全局函数相比效率会少许增长。
类中的函数一般都是有一个隐含的 this 指针,this指针指向类的对象本身,所以调用函数一般这样写fun();实际上是this->fun();
函数的调用:
class A
{
public:
static int add()
{}
};
int main()
{
A a;
a.add(); //通过对象调用静态成员函数
A::add(); //通过类名::函数 调用静态成员函数
return 0;
}
两个问题:
【问题1】:类的静态函数可以调用非静态函数吗?
答:不可以,静态成员函数之间可以互相访问,包括静态成员函数和静态成员变量。
因为在静态成员函数中调用非静态成员函数实际上要传参数,传this指针,但是静态函数并没有this指针,所以不能调。看看这段代码:
class test
{
public:
static void staticfoo()
{
memfoo();
}
void memfoo()
{}
}
int main()
{
test::staticfoo();
return 0;
}
以上是C++代码,翻译成C代码:
struct test
{
}
static void test_staticfoo()
{
memfoo(pthis); //pthis 参数并不存在
}
void memfoo(test* pthis)
{}
int main()
{
test_staticfoo();
return 0;
}
【问题2】:非静态函数可以调用类的静态函数吗?
答:可以,非静态函数可以随意的访问类的静态成员函数和静态成员变量。