static关键字java中也有, 是静态的意思, 在java中可以用来修饰变量和方法. 修饰变量时, 变量就成为类变量, 对于所有对象都具有相同的值; 修饰方法时, 方法就成为类方法, 不能访问成员变量.
c++中的关键字也类似, 用来修饰变量和方法, 不过比java中还稍微多一些功能:
(1) 修饰全局变量: 全局变量将仅在该文件内可用, 其它文件中无法访问到这个变量
(2) 修饰全局方法: 全局方法将仅在该文件内可用, 其它文件中将无法访问到这个方法
(3) 修饰局部变量: 可以将其看作static修饰的全局变量了, 只是作用范围变为局部, 和局部变量原来的作用范围相同.
(4) 修饰类变量: 和java中类似, 成为类变量, 对于所有对象都具有相同的值
(5) 修饰类方法: 和java中类似, 成员类方法, 不能访问成员变量.
(1)static修饰全局变量
Static.cpp
static int s_int = 10;
测试1, 通过声明extern int s_int; 看能不能访问到s_int
Main.cpp
#include <iostream>
using namespace std;
extern int s_int;
int main(void)
{
cout << "s_int:" << s_int << '\n';
}
编译代码, 编译器将提示错误: undefined reference to `s_int', 说明Main.cpp文件无法访问到Static.cpp中的s_int
测试2, 可以在多个文件中定义s_int变量, 且不会出现重定义的错误, 同时不同文件中定义的s_int变量都相互独立, 互不干扰.
Static2.cpp
static int s_int = 11;
Main.cpp
#include <iostream>
#include "Static.cpp" // include的效果就相当于把代码copy到Main.cpp的这里, 也就是相当于在Main.cpp的这里定义了s_int, 所以main中可以访问到s_int.
using namespace std;
int main(void)
{
cout << "s_int:" << s_int << '\n';
return 0;
}
#include "Static.cpp"时, 得到的结果是10; #include "Static2.cpp"时, 得到的结果将是11. 所以这个程序中其实是有两个相互独立的s_int存在.
(2) static修饰全局方法
Static.h
#ifndef STATIC_H_
#define STATIC_H_
static void staticMethod();
#endif
Static.cpp
#include <iostream>
using namespace std;
static void staticMethod()
{
cout << "staticMethod()" << '\n';
}
Main.cpp
#include <iostream>
#include "Static.h"
using namespace std;
int main(void)
{
staticMethod();
return 0;
}
编译后编译器会提示错误, 'void staticMethod()' used but never defined, 使用了staticMethod(), 但并没有定义他.
额, 不是在Static.cpp中定义了么?
和之前static修饰变量一样, static修饰全局方法后, Static.h和Static.cpp中的两个staticMethod()就变成了完全没有任何关系的两个独立的方法了, 那当然Static.h中的那个方法仅仅是声明了, 并没有定义.
解决办法, 那就是为Static.h中的那个staticMethod进行定义.
Static.h
#ifndef STATIC_H_
#define STATIC_H_
#include <iostream>
static void staticMethod();
static void staticMethod()
{
std::cout << "Static.h : staticMehtod()" << '\n';
}
#endif
(3) static修饰局部变量
其实就可以看作是static全局变量, 仅仅是作用范围变小, 仅在定义他的代码块中可以访问到.
同时他和局部变量也有一些区别, 局部变量在每次进入方法时初始化, 方法结束时回收掉, 而static局部变量是仅在第一调用方法时初始化, 接下来的调用将不再初始化, 且在方法结束时不会被回收掉.
Main.cpp
#include <iostream>
void localStatic()
{
static int s_int = 10;
std::cout << "s_int:" << s_int << '\n';
s_int++;
}
int main(void)
{
for (int i = 0; i < 10; i++)
{
localStatic();
}
}
(3) 修饰类变量时
Static.h
#ifndef STATIC_H_
#define STATIC_H_
class Static
{
public:
static int s_int;
}
#endif
Static.cpp
#include "Static.h"
int Static::s_int = 10;
Main.cpp
#include "Static.h"
#include <iostream>
int main(void)
{
Static s1;
Static s2;
std:: cout << "s1.s_int:" << s1.s_int << '\n';
std:: cout << "s2.s_int:" << s2.s_int << '\n';
// 修改后, 两个对象还是具有相同的值
s1.s_int = 11;
std:: cout << "s1.s_int:" << s1.s_int << '\n';
std:: cout << "s2.s_int:" << s2.s_int << '\n';
}
(3) 修饰类方法时
Static.h
#ifndef STATIC_H_
#define STATIC_H_
class Static
{
public:
int m_int;
static int s_int;
Static();
static void staticMethod();
}
#endif
Static.cpp
#include "Static.h"
Static::Static()
{
m_int = 1;
s_int = 2;
}
void Static::staticMethod()
{
// m_int = 3; // 无法访问成员变量
s_int = 4; // 类变量可以访问
}
Main.cpp
#include <iostream>
#include "Static.h"
int main(void)
{
Static s;
std::cout << "Static.m_int:" << s.m_int << '\n';
// 静态方法的调用和java中也类似, 既可以在对象上调用, 也可以使用类直接调用, 但推荐第二种.
s.staticMethod();
Static::staticMethod();
}