【C++】 ——C++关键字static的作用

static的用法

相信大家对这个关键字已经听到耳朵起茧子了吧,但是还是不清楚什么时候该用,什么时候不该用,但是这又是面试的时候经常会问的知识点,接下来我便结合其他博主的阐述,再次整理一下。

C++ static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static。前者主要用于普通变量和函数。后者主要用于static在类中的作用。

一、面向过程设计的satic

1.1 静态全局变量

在全局变量前加上关键字static ,该变量就会被定义成一个静态全局变量

如下:

satic int n;  //定义静态全局变量

void Function()
{
	n++;
	cout << n << endl;
}
int main()
{
	n = 20;
	cout << n << endl;
	Function();
	return 0;
}

那为什么我们不把static去掉,直接定义成int n呢?其实这也没错,程序会照样运行,但是定义成静态全局变量,还有以下好处:

  • 静态全局变量不能被其他文件所用;
  • 其他文件中可以定义相同名字的变量,不会发生冲突

就像是以下代码所示:

//文件1
#include <iostream>
#include <stdlib.h>
using namespace std;
static int n;  //定义静态全局变量
void fu();
int main()
{
	n = 20;
	cout << n << endl;
	system("pause");
	return 0;
}

//文件2
#include<iostream>
#include <stdlib.h>
using namespace std;

extern int n;  //定义相同名字的变量n

void fn()
{
	n++;
	cout << n << endl;
	system("pause");
}

此时我们发现,虽然单个文件时编译通过了,但是运行会报错,这就是我们之前所提到的:我们可以在另外一个文件定义与静态全局变量相同的变量名称,但是静态全局变量不能被这个文件使用。

静态全局变量的特点:

  • 该变量在全局数据区分配内存;(在全局数据区分配内存,函数运行结束,也不会释放空间)
  • 未经初始化的静态全局变量会被程序自动初始化为0(自动变量的值是随机的,除非它被显式初始化);
  • 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的;

1.2 静态局部变量

如下代码:

void fn()
{
	static int n = 10;
	cout<<n<<endl;
	n++;
}

在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存。但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。

那这里static的作用更加明显,第一次执行上述的fn函数,会输出n=10;当第二次执行fn的时候n=11,因为static可以对两次调用之间对变量的值进行保存。那这里我们就明白了为什么不能用int n=10了,因为这样定义,即使运行无数次fn,n的值还是10,不会变化。那为什么不直接定义成全局变量,把int n=10直接写到函数外面?因为如果这样定义的话,那这里这个变量就不再属于函数本身了,不受函数的限制,给程序维护带来不便。

静态局部变量有以下特点:

  • 该变量在全局数据区分配内存;
  • 静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
  • 静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
  • 它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;

1.3 静态函数

在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。

#include<iostream>
using namespace std;
 
static void fn();   //声明静态函数
 
int main(void)
{
	fn();
	return 0;
}
 
void fn()     //定义静态函数
{
	int n = 10;
	cout<<n<<endl;
}

定义静态函数的好处:

  • 静态函数不能被其它文件所用;
  • 其它文件中可以定义相同名字的函数,不会发生冲突;

二、面向对象设计的satic

2.1、静态数据成员

在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。先举一个静态数据成员的例子

#include<iostream>
using namespace std;
 
class Myclass
{
private:
	int a , b , c;
	static int sum;  //声明静态数据成员
public:
	Myclass(int a , int b , int c);
	void GetSum();
};
 
int Myclass::sum = 0;   //定义并初始化静态数据成员

我说的简单点吧:

  • 在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共用
  • 静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义,在以上代码中我们对静态数据成员sum在类外进行了初始化

2.2 静态成员函数

静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。

静态成员函数的定义如下:

#include<iostream>
using namespace std;
 
class Myclass
{
private:
	int a , b , c;
	static int sum;  //声明静态数据成员
public:
	Myclass(int a , int b , int c);
	static void GetSum();  //声明静态成员函数
};
 
int Myclass::sum = 0;   //定义并初始化静态数据成员
 
Myclass::Myclass(int a , int b , int c)
{
	this->a = a;
	this->b = b;
	this->c = c;
	sum += a+b+c;    //非静态成员函数可以访问静态数据成员
}
void Myclass::GetSum()    //静态成员函数的实现
{
	//cout<<a<<endl;    //错误代码,a是非静态数据成员
	cout<<"sum="<<sum<<endl;
}

与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数

总结静态成员函数:

  • 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
  • 非静态成员函数可以任意地访问静态成员函数和静态数据成员;
  • 静态成员函数不能访问非静态成员函数和非静态数据成员;
发布了33 篇原创文章 · 获赞 13 · 访问量 1016

猜你喜欢

转载自blog.csdn.net/Vicky_Cr/article/details/105234409
今日推荐