javaer学c++: static变量, static函数

阅读更多

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 

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 
#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 

using namespace std;

static void staticMethod()
{
    cout << "staticMethod()" << '\n';
}

Main.cpp
#include 
#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 

static void staticMethod();

static void staticMethod()
{
    std::cout << "Static.h : staticMehtod()" << '\n';
}

#endif





(3) static修饰局部变量
其实就可以看作是static全局变量, 仅仅是作用范围变小, 仅在定义他的代码块中可以访问到.
同时他和局部变量也有一些区别, 局部变量在每次进入方法时初始化, 方法结束时回收掉, 而static局部变量是仅在第一调用方法时初始化, 接下来的调用将不再初始化, 且在方法结束时不会被回收掉.

Main.cpp
#include 

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 

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 
#include "Static.h"

int main(void)
{
    Static s;
    std::cout << "Static.m_int:" << s.m_int << '\n';

    // 静态方法的调用和java中也类似, 既可以在对象上调用, 也可以使用类直接调用, 但推荐第二种.
    s.staticMethod();
    Static::staticMethod();
}



你可能感兴趣的:(static)