c++ static关键字
最近在看一个项目时,发现他源文件中有一些生涩的static用法,便去复习了一下关于static的用法,在这里总结一下。错漏之处,请不吝指正。
c中的static
1.函数内部变量定义
int fun()
{
static int n = 10;
return n--;
}
使用这种方式定义的变量,会存储在静态存储区。存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。也就是说,除了程序刚开始运行将n
初值设为10之外,后续每次调用函数只会执行n--
操作。
值得一提的是,n
的作用域只是在函数fun()
之内,但是它的生存期为整个源程序。也就是说,退出该函数后, 尽管该变量还继续存在,但不能使用它。
2.全局变量定义
static int n;
全局变量定义在函数体外部,在全局数据区分配存储空间,跟其他全部变量一样,编译器会自动对其初始化为0
。
使用static
关键字的意义在于,限定变量n
的作用域只在本文件内,在其他文件内不可见,也就避免了变量命名冲突。
注意:普通全局变量对整个工程可见,其他文件可以使用extern
外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。
3. 使用static对函数定义
static int fun()
{
int n = 10;
return n--;
}
与定义全局变量的作用相似,使用static
定义函数的意义在于,此函数只能在声明它的文件中可见,其他文件不能引用该函数,从而避免了函数命名冲突的发生。
c++中的static
主要是static
在类中的使用。
1. 在类中定义static变量
使用了static关键字,就说明该变量是类的静态成员变量。
- 静态数据成员存储在全局数据区,静态数据成员在定义时分配存储空间,所以不能在类声明中定义
- 静态数据成员是类的成员,无论定义了多少个类的对象,静态数据成员的拷贝只有一个,且对该类的所有对象可见。也就是说任一对象对静态成员变量的操作都是在对一个变量本身在操作。
- 静态数据成员不属于任何对象,在没有类的实例时其作用域就可见,在没有任何对象时,就可以进行操作。也就是说,无论是否实例化对象,静态成员都是存在的。无论实例化多少对象,静态成员也只会存在一个。
- 和普通数据成员一样,静态数据成员也遵从
public, protected, private
访问规则 - 静态数据成员的初始化格式:
<数据类型><类名>::<静态数据成员名>=<值>(
类外初始化) - 类的静态数据成员有两种访问方式:
<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名>
- 由于静态成员声明于类中,操作于其外,所以对其取地址操作,就多少有些特殊 ,变量地址是指向其数据类型的指针 ,函数地址类型是一个
nonmember
函数指针。 - 静态数据成员是静态存储的,所以必须对它进行初始化.(程序员手动初始化,否则编译时一般不会报错,但是在Link时会报错误)
- 为了防止父类的影响,可以在子类定义一个与父类相同的静态变量,以屏蔽父类的影响。这里有一点需要注意:我们说静态成员为父类和子类共享,但我们有重复定义了静态成员,为了避免这种错误的发生,我们的编译器采用了一种绝妙的手法:
name-mangling
用以生成唯一的标志。
注意:这里的类外初始化指的是只用static
修饰的类内变量,如果使用 static const
同时修饰的变量,是允许在类内初始化的。
2. 在类中定义static函数
与静态数据成员类似,静态成员函数属于整个类,而不是某一个对象。
- 静态成员函数没有this指针,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数
- 出现在类体外的函数定义不能指定关键字
static
- 非静态成员函数可以任意地访问静态成员函数和静态数据成员
- 不能将静态成员函数定义为虚函数。
- 由于静态成员函数没有
this
指针,所以就差不多等同于nonmember
函数,结果就 产生了一个意想不到的好处:成为一个callback
函数,使得我们得以将C++
和C-based X Window
系统结合,同时也成功的应用于线程函数身上。 - static并没有增加程序的时空开销,相反她还缩短了子类对父类静态成员的访问 时间,节省了子类的内存空间。