【C++】C++中的关键字static详解

本文详细介绍了C++中的`static`关键字在静态成员变量、静态成员函数、全局变量和静态函数中的应用。`static`用于限制作用域,实现数据隔离和持久性,同时探讨了在头文件中使用`static`可能导致的问题和解决方案。通过实例展示了静态成员如何实现数据共享,并讨论了使用`static`的原因和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一.静态成员

1.静态成员变量

2.静态成员函数

二.全局变量及函数和静态变量及函数

1.全局变量和函数

2.静态变量及函数

三.为什么要用static

1.保护数据,做到数据隔离

2.维持数据的持续性


省时间读这里:

开发中static是为了限制其作用域只在定义该变量或函数的源文件内有效,而在同一工程下的其他源文件中不能使用。

遇到的问题:

Q:头文件中定义了static变量或函数,只要引入该头文件,还是可以使用这些static修饰的变量或函数,为什么?

A:含了该头文件的所有源文件中都定义了这些变量,即该头文件被包含了多少次,这些变量就定义了多少次,导致实际上同名变量值却不同。

一.静态成员

静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员,静态成员只能在当前源文件使用。
静态成员分为:

1.静态成员变量

  • 所有对象共享同一份数据

  • 在编译阶段分配内存

  • 类内声明,类外初始化

#include <iostream>]
using namespace std;
class Person
{
public:

	static int m_A; //静态成员变量

	//静态成员变量特点:
	//1 在编译阶段分配内存
	//2 类内声明,类外初始化
	//3 所有对象共享同一份数据

private:
	static int m_B; //静态成员变量也是有访问权限的
};
//在类外初始化
int Person::m_A = 10;
int Person::m_B = 10;

void test01()
{
	//静态成员变量两种访问方式

	//1、通过对象
	Person p1;
	p1.m_A = 100;
	cout << "p1.m_A = " << p1.m_A << endl;

	Person p2;
	p2.m_A = 200;
	cout << "p1.m_A = " << p1.m_A << endl; //共享同一份数据
	cout << "p2.m_A = " << p2.m_A << endl;

	//2、通过类名
	cout << "m_A = " << Person::m_A << endl;


	//cout << "m_B = " << Person::m_B << endl; //私有权限访问不到
}

int main() {

	test01();

	system("pause");

	return 0;
}

上面代码输出:

p1.m_A = 100
p1.m_A = 200
p2.m_A = 200
m_A = 200 

2.静态成员函数

  • 所有对象共享同一个函数

  • 静态成员函数只能访问静态成员变量

#include <iostream>
using namespace std;
class Person
{
public:

	//静态成员函数特点:
	//1 程序共享一个函数
	//2 静态成员函数只能访问静态成员变量
	
	static void func()
	{
		cout << "func调用" << endl;
		m_A = 100;
		//m_B = 100; //错误,不可以访问非静态成员变量
	}

	static int m_A; //静态成员变量
	int m_B; // 
private:

	//静态成员函数也是有访问权限的
	static void func2()
	{
		cout << "func2调用" << endl;
	}
};
int Person::m_A = 10;


void test01()
{
	//静态成员变量两种访问方式

	//1、通过对象
	Person p1;
	p1.func();

	//2、通过类名
	Person::func();


	//Person::func2(); //私有权限访问不到
}

int main() {

	test01();

	system("pause");

	return 0;
}

上面代码输出:

func调用
func调用

二.全局变量及函数和静态变量及函数

1.全局变量和函数

一般变量函数默认都为全局的。
全局变量及函数:在当前源文件以及其他源文件都可以使用,如果其他源文件使用需要extern对全局变量及函数进行声明。使用extern声明变量时不能带有初始值,否则仍然属于变量定义,会出现变量重定义的错误。

使用extern关键字

test.cpp

#include <iostream>
using namespace std;
// 定义为外部变量
extern int num = 100;
// 定义为外部函数
extern void fun() {
	cout << "test.cpp - fun()" << endl;
}

main.cpp

// main.cpp
#include <iostream>
using namespace std;

extern void fun();
extern int num;

void test() {
	fun();	// test.cpp - fun()
	cout << num << endl;	// 100
}

int main()
{
	test();
	system("pause");
	return 0;
}

2.静态变量及函数

使用static关键字

加修饰的变量和函数。
静态成员只能在当前源文件使用,其他源文件不能使用,但是如果在头文件中声明并定义了static变量或函数,那么引入该头文件的源文件也可以使用static变量或函数,这时候就感觉和刚刚说的相违背,但其实定义全局变量时使用static,意味着该变量的作用域只限于定义它的源文件中,其它源文件不能访问。既然这种定义方式出现在头文件中,那么可以很自然地推测:包含了该头文件的所有源文件中都定义了这些变量,即该头文件被包含了多少次,这些变量就定义了多少次。

假如将上面两行代码的static去掉,编译的时候就会出现变量重定义的错误,这进一步证实了上面的推测,因为没有static的话变量的作用域是全局的,定义了两个以上的同名变量就会出现该错误。

所以,在头文件中定义static变量会造成变量多次定义,造成内存空间的浪费,而且也不是真正的全局变量。应该避免使用这种定义方式。

静态变量和函数具体分为以下几种:

在类外定义:

1、静态全局变量

        使用:全局变量前加static,修饰全局变量为静态全局变量。

        作用:改变全局变量的可见性。静态全局变量的存储位置在静态存储区,未被初始化的静态全局变量会被自动初始化为0。静态全局变量在声明它的文件之外是不可见的,仅在从定义该变量的开始位置到文件结尾可见。

  2、静态局部变量

       使用:局部变量前加static,修饰局部变量为静态局部变量。

       作用:改变局部变量的销毁时期。静态局部变量的作用域和局部变量的作用域一样,当定义它的函数或语句块结束的时候,作用域结束。不同的是,静态局部变量存储在静态存储区,当静态局部变量离开作用域后,并没有被销毁。当该函数再次被调用的时候,该变量的值为上次函数调用结束时的值。

  3、静态函数

        使用:函数返回类型前加static,修饰函数为静态函数。

        作用:改变函数的可见性。函数的定义和声明在默认情况下都是extern的,但静态函数只在声明它的文件中可见,不能被其他文件使用。

在类内定义:

最开始使用的案例代码都是在类中定义的类的静态成员变量和类的静态成员函数

  4、类的静态成员变量

        使用:类成员前加static,修饰类的成员为类的静态成员。

        作用:实现多个对象之间的数据共享,并且使用静态成员不会破坏封装性,也保证了安全性。

class Person
{
public:
static int m_A; //静态成员变量
}

  5、类的静态成员函数

        使用:类函数前加static,修饰类的函数为静态函数。

        作用:减少资源消耗,不需要实例化就可以使用。

class Person
{
public:
static void func()
	{
		cout << "func调用" << endl;
		m_A = 100;
		//m_B = 100; //错误,不可以访问非静态成员变量
	}
}

三.为什么要用static

1.保护数据,做到数据隔离

        根据上面使用全局变量的方法,全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,全局变量在所有的源文件中都是有效的。如果希望全局变量仅限于在本源文件中使用,在其他源文件中不能引用,也就是说限制其作用域只在定义该变量的源文件内有效,而在同一源程序的其他源文件中不能使用,这时,就可以通过在全局变量上加static来实现,使全局变量被定义成一个静态全局变量。这样就可以避免其他源文件使用该变量、避免其他源文件因为该变量引起的错误。

2.维持数据的持续性

        静态变量和静态函数的生命周期是整个进程,存储在全局静态存储区,全局变量和静态变量的存储都放在这里, 有时候,我们希望函数中局部变量的值在函数调用结束之后不会消失,仍然保留函数调用结束的值。这时可以将该局部变量用关关键字static声明为静态局部变量。当局部变量被声明为静态局部变量的时候,也就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区存放,全局变量也存放在静态存储区。静态局部变量与全局变量的主要区别就在于可见性,静态局部变量只在其被声明的代码块中是可见的。



 

### Java 中 `static` 关键字的作用 在 Java 编程语言中,`static` 关键字用于定义独立于对象的静态变量、方法以及嵌套类。这意味着这些成员属于整个类而不是某个特定的对象实例[^1]。 #### 静态变量 (Class Variables) 当声明为 `static` 的时候,该字段成为类级别的属性而非实例级别。无论创建多少个此类的对象,都只会存在一份这样的数据副本被所有实例所共享: ```java public class Counter { public static int count = 0; // 类级变量 public Counter() { count++; } } ``` 每次新建一个 `Counter` 对象时都会增加计数器 `count` 的值,并且这个变化会影响到其他地方对该静态域的访问。 #### 静态方法 (Static Methods) 带有 `static` 修饰符的方法可以直接通过类名调用而无需先实例化任何对象。这类函数通常用来执行一些不依赖具体状态的操作或是作为工具性质的功能实现: ```java public class MathUtils { public static double squareRoot(double num){ return Math.sqrt(num); } } // 使用方式如下: double result = MathUtils.squareRoot(9); System.out.println(result); // 输出3.0 ``` 需要注意的是,在静态上下文中无法直接引用非静态成员因为后者是与具体的对象关联在一起的。 #### 静态初始化块 (Static Initializer Blocks) 除了单个语句外还可以利用大括号包裹起来的一组表达式来完成更复杂的逻辑处理工作——这就是所谓的“静态初始器”。它会在加载类到 JVM 后立即被执行一次,常用于资源预分配等场景下: ```java class DatabaseConnection{ private static Connection conn; static { try{ Class.forName("com.mysql.jdbc.Driver"); String url="jdbc:mysql://localhost:3306/test"; String user="root"; String password=""; conn=DriverManager.getConnection(url,user,password); }catch(Exception e){e.printStackTrace();} } } ``` 这段代码展示了如何建立数据库连接并将其存储在一个静态变量里供后续操作使用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员赵大宝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值