static用法,作用

来源:互联网 发布:淘宝推广返利 编辑:程序博客网 时间:2024/06/02 02:00

1.隐藏功能:

当我们声明一个全局函数和变量时函数默认的前面加的是extern

全局变量和函数都具有全局可见性,也就是在a文件中声明的也能在b文件中使用。

 

 

如果加了static,就会对其它源文件隐藏。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏.

 

中间小插曲:

extern作用

extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量或函数时,在其它模块中寻找其定义。另外,extern也可用来进行链接指定。

 

extern用在变量声明中常常有这样一个作用:你要在*.c文件中引用另一个文件中的一个全局的变量,那就应该放在*.h中用extern来声明这个全局变量。

就是说如果我想用别的文件的全局变量,应该在头文件中用extern来声明这个变量,而且在本文件中引用头文件。

 

 

extern int a;  //声明一个全局变量a

int a;      //定义一个全局变量a

extern int a =0 ; //定义一个全局变量a 并给初值。一旦给予赋值,一定是定义,定义才会分配存储空间。

int a =0;  //定义一个全局变量a,并给初值。

当你要引用一个全局变量的时候,你就要声明externint a;这时候extern不能省略因为省略了,就变成int a;这是一个定义,不是声明。

 

实例:

//A.cpp

int i;

int main()

{

}

//B.cpp

int i;

 

两个文件单独编译的话是没有什么问题的。若在整个项目中,如果把两个文件链接起来的时候就会出现错误,这是因为有两个强符号。

 

要想解决这个问题就要在这个变量前面加上static

如果加上了static就会对变量实现隐藏。利用这一特性就可以在函数不同文件中定义同名函数和同名变量而不用担心命名的冲突。对于函数来讲,static的作用仅限于隐藏.

 

 

 

 //A.cpp

int main()

{

    i = 100;//试图使用B中定义的全局变量

}

//B.cpp

int i;

 

在分别对两个文件进行编译的时候 A就会出现错误,原因是A中没有变量的i的声明,虽然B文件中有,但只有当两个文件进行链接的时候才可以。

解决方法:

//A.cpp

extern int i;

int main()

{

    i=100;//试图使用B中定义的全局变量

}

//B.cpp

int i;

在A文件中加入extern int i;这句话告诉编译器,i在别的文件中已经定义了。放心,在链接的时候就可以用。

2.保持变量内容的持久(这个是对变量的单独作用)

存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围。指的是在函数内声明。

 

如果作为static局部变量在函数内定义,它的生存期为整个源程序,但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。(就是生存期和整个程序相同,只是作用域可以控制为函数体中,不仅可以有全局作用域,还可以有局部作用域)。而全局变量的作用域,只能在全局了。

 

在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置0,然后把不是0的几个元素赋值。如果定义成静态的,就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加‘\0’;太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是‘\0’;

 

 

 

3.C++中的类成员声明static(有些地方与以上作用重叠)

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

 

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

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

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

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

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

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

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

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

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

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

0 0
原创粉丝点击