一、隐藏作用

指的是加static关键字的变量只在源文件cpp中起作用,无法在其中文件中被调用。

举例来说明:

分别创建两个cpp文件。一个是main函数所处的cpp 一个是自己定义的demo.cpp

demo.cpp代码如下:里面主要是定义了一个char类型字符a和msg函数

#include "stdafx.h"

char a ='a';
void msg(){
std::cout << "demo" << std::endl;
}

main.cpp代码如下:主要是通过extern 来引用这两个方法 并执行

#include "stdafx.h"
#include "demo.h"

using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
extern char a;
extern void msg();
cout<< a << endl;
msg();
return 0;
}

此时是未加入static关键字运行结果:

C++ static关键字作用讲解_静态成员

 

此时可以看到,a和msg()方法均被引用到,现在在demo.cpp中加上static关键词,看看会发生什么情况:

#include "stdafx.h"

static char a ='a';
static void msg(){
std::cout << "demo" << std::endl;
}

运行结果如下:

C++ static关键字作用讲解_初始化_02

可以很容易看出 它无法被引用,说明在c++中 变量加上static 有隐藏的作用

二、封装在函数中,保持变量的持久性

这种理解起来可能有点难,通俗的来讲,就是在函数中,如果初始化一次之后,之后多次调用函数,这个参数就无需再初始化,因为该值已经保存了。

用示例来讲解:

一种是加了static的代码:

// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "demo.h"
using namespace std;

int func(){
static int i_count = 10;
return i_count--;
}

int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 0 ; i < 10 ; i++)
{
int dd = func();
cout << dd <<endl;
}
return 0;
}

代码比较简单。就是执行10次func函数,运行结果:

C++ static关键字作用讲解_静态成员_03

可以很明显的从结果中看出来,static的参数i_count 就初始化了一次。

接下来不加static 我们来看看

// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "demo.h"
using namespace std;

int func(){
int i_count = 10;
return i_count--;
}

int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 0 ; i < 10 ; i++)
{
int dd = func();
cout << dd <<endl;
}
return 0;
}

运行结果:

C++ static关键字作用讲解_#include_04

非常明显可看出来,它每调一次都会初始化一次,比较方便大家理解。

 

三、static变量初始化为0 

原理:静态数据区,内存字节默认为0x00;you know

示例:

#include "stdafx.h"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
int i ;
static int m;
cout << i << endl;
return 0;
}

首先是输出没加static的变量i 我们看结果:

C++ static关键字作用讲解_初始化_05

明显可以看到without being initialized 可以看到未被初始化,

接下来我们来看一下输出加static之后的i 会发生什么呢。

C++ static关键字作用讲解_静态成员_06

可以看到i输出了,说明加上static 会先默认初始化为0。

 

四、static在C++类成员中的作用:

 在类中声明static变量或者函数时,初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员,这样就出现以下作用:

(1)类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致 了它仅能访问类的静态数据和静态成员函数。     

示例代码:

//头文件.h
#include "stdafx.h"
using namespace std;

class Demo{
public:
Demo();
~Demo();
static int d ;
static void demod();
void msg();
int cb_str;
};

//.cpp
#include "stdafx.h"
#include "demo.h"
using namespace std;

//extern int var_str;
Demo::Demo(){
cb_str = 2;
//int Demo::d = 2;
//var_str = 2;
}
//static Demo::var_str = 2;

Demo::~Demo(){

}

int Demo::d = 1;

void Demo::demod(){
//cout << cb_str << endl; //访问其他变量出错
cout << d << endl;
}
void Demo::msg()
{
}

这里可以看出 d 属于静态成员变量 cb_str属于非静态成员变量 接下来静态成员函数demod 引用非静态成员变量 cb_str 运行 查看效果如下:

C++ static关键字作用讲解_静态成员_07

实际操作可知:它仅能访问类的静态数据和静态成员函数。     

(2)不能将静态成员函数定义为虚函数。      

(3)由于静态成员声明于类中,操作于其外,所以对其取地址操作,就多少有些特殊 ,变量地址是指向其数据类型的指针 ,函数地址类型是一个“nonmember函数指针”。

(4)由于静态成员函数没有this指针,所以就差不多等同于nonmember函数,结果就 产生了一个意想不到的好处:成为一个callback函数,使得我们得以将C++和C-based X W indow系统结合,同时也成功的应用于线程函数身上。 (这条没遇见过)  

(5)static并没有增加程序的时空开销,相反她还缩短了子类对父类静态成员的访问 时间,节省了子类的内存空间。      

(6)静态数据成员在<定义或说明>时前面加关键字static。      

(7)静态数据成员是静态存储的,所以必须对它进行初始化。 (程序员手动初始化,否则编译时一般不会报错,但是在Link时会报错误) 

(8)静态成员初始化与一般数据成员初始化不同:

初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆;
初始化时不加该成员的访问权限控制符private,public等;        
初始化时使用作用域运算符来标明它所属类;
           所以我们得出静态数据成员初始化的格式:
<数据类型><类名>::<静态数据成员名>=<值>

(9)为了防止父类的影响,可以在子类定义一个与父类相同的静态变量,以屏蔽父类的影响。这里有一点需要注意:我们说静态成员为父类和子类共享,但我们有重复定义了静态成员,这会不会引起错误呢?不会,我们的编译器采用了一种绝妙的手法:name-mangling 用以生成唯一的标志。

 

希望对大家有帮助吧 这个概念还是很基础的 但是最终还是实际上用出来比较好。

接下来后面写const关键字的作用,这两个比较面试常考