1. static关键字的出现
static关键字用于实现封装性、数据共享、信息隐藏、生命周期控制和命名冲突的解决方案;
1.1 封装性
封装性:静态成员变量和静态成员函数是与类关联而不是与类的实例相关联的。通过将数据和方法声明为静态,可以将其与类本身紧密绑定,而不是依赖于类的实例。这提高了代码的封装性,并使得访问和使用静态成员更加简洁和一致。
1.2 数据共享
数据共享:静态成员变量在类的所有实例之间共享,可以用于存储所有实例间共享的数据。这种共享数据的方式可以节省内存空间,并且保证了对共享数据的统一访问和修改。
1.3 信息隐藏
信息隐藏:静态成员函数可以直接通过类名调用,而不需要创建类的实例,这意味着可以在不暴露实例化对象的情况下访问特定的函数。这样做可以通过隐藏内部实现细节来提供更好的抽象和封装性。
1.4 生命周期控制
生命周期控制:静态局部变量的生命周期在整个程序执行期间保持不变。它们在第一次声明时初始化,并且在程序结束时才会被销毁。这使得静态局部变量成为保存状态的有效工具,例如计数器、缓存等。
1.5 简化命名冲突
简化命名冲突:静态变量和静态函数的作用域限于当前文件或当前类,这可以帮助避免与其他文件中的同名变量或函数发生命名冲突。这种限制使得静态关键字在管理全局标识符时起到了重要的作用。
2.static的应用场景
2.1 静态成员变量
静态成员变量(Static Member Variables):在类中声明的静态成员变量是与类本身相关联而不是与类的实例相关联的。这意味着不管创建了多少类的实例,静态成员变量的内存只有一份。静态成员变量在类的所有实例之间共享,并且可以通过类名加作用域限定符来访问。
2.2 静态成员函数
静态成员函数(Static Member Functions):类中声明的静态成员函数不依赖于特定的类实例。它们可以使用类的静态成员变量,但不能使用非静态成员变量。静态成员函数可以直接通过类名来调用,而不需要创建类的实例。
示例
#include <iostream>
class StaticTest
{
public:
StaticTest(){
m_name = "static test";
}
~StaticTest(){}
public:
//可以是成员函数,也可以是静态成员函数,都可以范围静态变量
void addValue()
{
m_value++;
}
//可以是成员函数,也可以是静态成员函数,都可以范围静态变量
void printValue()
{
std::cout<<"m_value is: "<<m_value<<std::endl;
}
//如果是静态成员函数,则不能访问m_value;静态成员函数只能访问静态成员变量
void printName()
{
std::cout<<"name is: "<<m_name;
}
private:
static int32_t m_value;
std::string m_name;
};
//在类外对静态成员变量进行初始化
int32_t StaticTest::m_value = 9;
void f()
{
static int32_t a = 100;
a++;
std::cout<<a<<std::endl;
}
int main(int argc, char* argv[])
{
StaticTest st;
st.addValue();
st.printValue(); //输出结果是10,因为st调用了addValue函数,对应数值会加1
StaticTest st1;
st1.addValue();
st1.printValue(); //输出结果是11,因为st调用了addValue函数,对应数值会加1
st.printValue(); //输出结果是11,因为st1调用了addValue函数
return 0;
}
输出
m_value is: 10
m_value is: 11
m_value is: 11
2.3 局部静态变量
局部静态变量(Static Local Variables):在函数内部声明的静态变量被称为局部静态变量。与自动变量(例如函数参数和局部变量)不同,局部静态变量在函数调用之间保持它们的值,并且只在第一次进入声明处时进行初始化。
示例
#include <iostream>
void f()
{
static int32_t a = 100;
a++;
std::cout<<a<<std::endl;
}
int main(int argc, char* argv[])
{
f();
f();
f();
return 0;
}
输出
101
102
103
2.4 文件作用域
静态关键字用于文件作用域(Static in File Scope):当静态关键字用于文件范围的变量或函数时,它们只在当前文件中可见,不能被其他文件访问。这种限制有助于避免命名冲突和符号重复定义的问题。
示例
#include <iostream>
static int32_t a = 100;
void f()
{
a++;
std::cout<<a<<std::endl;
}
int main(int argc, char* argv[])
{
f();
std::cout<<a<<std::endl;
f();
std::cout<<a<<std::endl;
return 0;
}
输出
101
101
102
102