c++ static(详解)
在C++中,static关键字用于定义具有静态存储持续时间的变量或方法。它在不同上下文中有不同的含义,通常与变量的存储方式和作用域相关。static的主要作用是控制变量或函数的可见性和生命周期。
可以通过一个生活中的场景来形象化static的作用:
场景:
假设你是一位图书馆管理员,负责管理图书馆中每个人的借书记录。每次有新成员登记时,你都为他们创建一个新的借书账户,并记录他们借的书。但图书馆有一个总借书数的统计,也就是说,不管有多少个会员借书,所有人的借书数量都会加在一起,形成一个全馆的总借书数。
静态变量的作用:
- 借书账户的个人记录:每个会员都有自己借书的记录(类似于类的普通成员变量),每个人只能看到自己借了几本书。
- 图书馆的总借书数:图书馆有一个总借书数的统计,这个数字对所有会员来说是共享的(类似于
static
成员变量),每个会员借了一本书后,这个总数都会增加。
对应到C++代码:
#include <iostream>using namespace std;class LibraryMember{
public:int personalBorrowedBooks = 0; //个人借书记录static int totalBorrowedBooks; //总借书数(所有人共享)void borrowBook(){personalBorrowedBooks++; //总借书数增加totalBorrowedBooks++; //总借书数增加}void showBorrowInfo(){cout <<"You have borrowed " << personalBorrowedBooks << " books." << endl;cout <<"The liberary has loand out " << totalBorrowedBooks << " book in total." << endl;}};//初始化静态成员变量
int LibraryMember::totalBorrowedBooks = 0;int main(){LibraryMember member1;LibraryMember member2;member1.borrowBook(); // member1借了1本书member2.borrowBook(); // member2借了1本书member1.borrowBook(); // member1又借了1本书cout << "memeber1 Info " << endl;member1.showBorrowInfo() ; // 显示member1的信息cout << "memeber2 Info " << endl;member2.showBorrowInfo(); // 显示member2的信息return 0;
}
输出结果:
memeber1 Info
You have borrowed 2 books.
The liberary has loand out 3 book in total.
memeber2 Info
You have borrowed 1 books.
The liberary has loand out 3 book in total.
分析:
- 个人借书记录(非静态成员变量):每个
LibraryMember
对象有自己独立的借书记录。member1
借了2本书,而member2
借了1本书,他们各自的记录是独立的。 - 总借书数(静态成员变量):所有成员共享一个总借书数,不管是哪个成员借了书,这个总借书数都会增加。
静态的现实意义:
static
就像图书馆的总借书统计,它不会因为某个会员的加入或离开而被重新设置或注销,始终保持一个全局的、共享的状态。这类似于生活中我们对一些全局、共享数据的统计与追踪,所有人都可以贡献,但数据是统一维护的。
1. 静态成员变量
静态成员变量(类的静态变量)属于整个类,而不是某个具体的对象。它们在所有对象中共享,也就是说,不管创建了多少个类对象,静态成员变量在内存中只有一份,且对所有对象都是共用的。
- 作用:用于存储类的全局状态,所有对象共享该状态。
class MyClass {
public:static int staticVar;MyClass() { staticVar++; } // 每次创建对象时都会递增
};int MyClass::staticVar = 0; // 静态变量需要在类外初始化int main() {MyClass obj1;MyClass obj2;cout << MyClass::staticVar; // 输出 2
}
2. 静态成员函数
静态成员函数和静态成员变量类似,它们属于整个类,而不是某个对象。静态成员函数只能访问静态成员变量,不能访问非静态成员变量,因为非静态成员变量依赖于具体的对象实例。
- 作用:用于不依赖对象的功能实现,比如操作静态成员变量。
class MyClass {
public:static int staticVar;static void printStaticVar() {cout << staticVar << endl; // 可以访问静态变量}
};int MyClass::staticVar = 0;int main() {MyClass::printStaticVar(); // 直接通过类名调用静态函数
}
3. 静态局部变量
在函数内部,static
局部变量的生命周期贯穿整个程序的执行,而不仅仅是在函数调用期间。它在函数第一次被调用时初始化,并在程序的整个生命周期内保持其值。
- 作用:用于需要在函数多次调用时保持其状态的场景。
void countCalls() {static int count = 0; // 只初始化一次count++;cout << "This function has been called " << count << " times" << endl;
}int main() {countCalls(); // 输出 1countCalls(); // 输出 2countCalls(); // 输出 3
}
4. 静态全局变量
static
修饰的全局变量(在函数或类外定义)只能在定义它的文件中访问,无法被其他文件访问。这是一种用于控制链接的方式,通常用于实现模块间的数据隔离,防止名称冲突。
- 作用:用于在一个源文件中定义只对该文件可见的变量。
static int fileVar = 0; // 只能在当前文件中使用
5. 静态函数(文件作用域)
类似于静态全局变量,static
修饰的函数只能在定义它的文件中使用。这在大型项目中非常有用,因为它可以防止不同文件中的函数名冲突。
- 作用:用于限制函数的可见性,使其仅在定义的文件中可用。
static void helperFunction() {// 只能在当前文件中调用
}
6. 使用场景总结
- 共享类成员:静态成员变量和静态成员函数在类的不同实例之间共享数据。
- 维护函数状态:静态局部变量用于在函数调用之间保持状态。
- 文件级作用域:静态全局变量和静态函数用于实现文件内的变量和函数封装,避免命名冲突。
- 效率提升:静态成员函数可以在不创建对象的情况下直接调用,减少对象的开销。
static
在C++中用于控制变量或函数的生命周期和作用域,在代码优化、模块化设计等方面发挥着重要作用。