每日一问13:C++中static关键字的作用

C++中static关键字的作用

1.隐藏

​ 在同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。如果加了static,就会对其它源文件隐藏。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏.

//a.c
char a = 'A'; 			// 全局变量
void msg()				// 函数
{
     printf("Hello
");
}
 
//main.c
#include<stdio.h>
void msg();				//使用全局函数前需要声明
int main()
{
     extern char a; 	//使用全局变量前需要声明
     printf("%c ", a);
     msg();
     return 0;
}

运行结果是:

在变量a和函数msg的声明前加上static后,再次编译:

2. 保持局部变量内容持久

​ 修饰局部变量时,使得该变量不会因为函数终止而丢失,使其生命周期为整个源程序。把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。

#include <stdio.h>
 
int fun(){
    static int count = 10; //在第一次进入这个函数的时候,变量a被初始化为10!并接着自减1,以后每次进入该函数,a
    return count--; //就不会被再次初始化了,仅进行自减1的操作;在static发明前,要达到同样的功能,则只能使用全局变量:    
 
}
int count = 1;
 
int main(void)
{
     printf("global		local static
");
     for(; count <= 10; ++count)
               printf("%d		%d
", count, fun());
     return 0;
}

3. 默认初始化为0

​ 全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。

#include <stdio.h>
 
int a;
 
int main()
{
     int i;
     static char str[10];
     printf("integer: %d; string: (%s)", a, str);
     return 0;
}

4. 类中的static

​ 在类中使用static的目的是为了实现共享。因为静态成员函数和静态成员变量属于类,不属于类的实体,这样可以被多个对象所共享,同时静态成员函数调用方便,不需要生成对象就能调用。

在类中声明static变量或者函数时,初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员,就出现以下注意事项:

(1)类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致 它仅能访问类的静态数据和静态成员函数。

(2)不能将静态成员函数定义为虚函数。

(3)由于静态成员声明于类中,操作于其外,所以对其取地址操作,变量地址是指向其数据类型的指针 ,函数地址类型是一个“非成员函数指针”。

(4)static并没有增加程序的时空开销,相反她还缩短了子类对父类静态成员的访问 时间,节省了子类的内存空间。

(5)静态数据成员在<定义或说明>时前面加关键字static。

(6)静态数据成员是静态存储的,所以必须对它进行初始化。 (程序员手动初始化,否则编译时一般不会报错,但是在Link时会报错误)

(7)静态成员初始化与一般数据成员初始化不同:

  • 初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆;
  • 初始化时不加该成员的访问权限控制符private,public等;
  • 初始化时使用作用域运算符来标明它所属类;
  • 静态数据成员初始化的格式:
    <数据类型><类名>::<静态数据成员名>=<值>

(8)为了防止父类的影响,可以在子类定义一个与父类相同的静态变量,以屏蔽父类的影响。这里有一点需要注意:我们说静态成员为父类和子类共享,但我们有重复定义了静态成员,这会不会引起错误呢?不会,我们的编译器采用了一种绝妙的手法:name-mangling 用以生成唯一的标志。

5. 问答

(1)在头文件把一个变量申明为static变量,那么引用该头文件的源文件能够访问到该变量吗。

答:可以。声明static变量一般是为了在本cpp文件中的static变量不能被其他的cpp文件引用,但是对于头文件,因为cpp文件中包含了头文件,故相当于该static变量在本cpp文件中也可见。当多个cpp文件包含该头文件中,这个static变量将在各个cpp文件中将是独立的,彼此修改不会对相互有影响。

(2)为什么静态成员函数不能申明为const

答:这是C++的规则,在类中,const修饰符用于表示函数不能修改成员变量的值,并且const实际修饰的就是指向类的this函数,而类中的static函数本质上是全局函数,不能用const来修饰它。一个静态成员函数可以访问的值是其参数、静态数据成员和全局变量,而这些数据都不是对象状态的一部分。而对成员函数中使用关键字const的作用是表明:函数不会修改该函数访问的目标对象的数据成员。既然一个静态成员函数根本不访问非静态数据成员,那么就没必要使用const了

(3)为什么不能在类的内部定义以及初始化static成员变量,而必须要放到类的外部定义

答:因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的。

(4)static关键字为什么只能出现在类内部的声明语句中,而不能重复出现在类外的定义中。

答:如果类外定义函数时在函数名前加了static,因为作用域的限制,就只能在当前cpp里用,类本来就是为了给程序里各种地方用的,其他地方使用类是包含类的头文件,而无法包含类的源文件。

static还可以根据其修饰的对象分为以下五种:

  • 静态成员变量(面向对象)
  • 静态成员函数(面向对象)
  • 静态全局变量(面向过程)
  • 静态局部变量(面向过程)
  • 静态函数(面向过程)

具体的分析可见:https://zhuanlan.zhihu.com/p/37439983

原文地址:https://www.cnblogs.com/honernan/p/14478366.html