关于C跟C++和C#之间的static

关于C和C++和C#之间的static

时间:2014.04.25

地点:基地

----------------------------------------------------------------------

一、引出

  关于C和C++和C#中的static一直想找个机会总结,它们都有这个关键字,可把我乐坏了也累坏了,关于C++中的static用法倒是在一篇博文中已经提到过,无非是类中的静态成员和方法,函数中的静态成员和静态链接三大用处,而且函数中的静态成员还不推荐使用。下面该是灭掉三大语言中的static的时候了。

----------------------------------------------------------------------

二、C时代中的static

  C中只存在函数和变量:

1.当在函数和全局变量前用static修饰时,说明该函数或变量只有本文件才能看的到,也就是说函数和变量是静态的或者说是内部的,别的文件看不到,也不会和别的文件中定义相同的函数名或变量名发生冲突。

2.局部变量被static修饰时,生命周期就是整个应用程序了,相当于是一个全局变量,但只是只有该函数才有权限访问,哦,也就是说,我们在函数内部定义了一个全局变量。

值得注意的是,对于全局变量这种外部变量,无论是否它被static修饰,它都是存储在静态存储区的,即static不是改变外部变量的存储方法,仅仅是限制它的作用范围为此文本。而对于局部变量也就是函数内定义的普通变量,它是分配在栈上的,函数调用完了就没了,但函数内定义的static变量依然是存储在静态存储区上,生存周期也一直在整个程序中有效,不会随着函数的调用完毕而消失,而且这种局部定义的静态变量是在第一次调用它时创建和初始化,且只有一次,没给初值的话就是0或空(指针),而局部变量则若初始值则默认是未知的。

例如

//first.c
int g_i=0;  //外部变量(全局变量)在静态存储区上
static int g_is=0;//内部变量(静态变量)在静态存储区上
int f1()       //定义了一个外部(全局)函数
{
    return 1;
}
static int f2()        //定义了一个静态(内部)函数
{
    return 2;
}

//和first.c在同一工程下的second.c
extern int g_i;        //引用文件first.c中的全局变量
extern int g_is;       //声明这里有一个g——is的变量是来自外部全局变量g_is
extern int f1()       ;//声明f1是外部函数
extern int f2();       //声明f2也是外部函数    
#include <stdio.h>
void main()
{
    printf("%d\n",g_i);
    //printf("%d\n",g_is);    //编译不通过,因为g_is在first.c中时静态的,外界是看不到的,所以找不到这样一个外部变量
    printf("%d\n",f1());
    //printf("%d\n",f2());    //编译不能通过,道理同上
}

这以上两点在C++中也类似的用法。

----------------------------------------------------------------------

三、C++时代的static

  C++是向C兼容的,所以有两点用法和C相同是应该的,不相同则不应该。但C++是面向对象的,由此会扩展出新的用法:可用于修饰类的数据成员和函数成员,以表明这个数据成员或方法属于类本身,而不具体到某个对象,各对象之间这个方法或这个数据是共享的。即便是在类的成员函数中定义了静态数据成员,在各个对象之间也会共享,这样纸真的不好。注意static不能修饰构造函数和析构函数,这是显然的嘛,各个对象必须有自己的构造和析构。

值得注意的是C++中类的静态成员函数是不能访问非静态字段的,我们也尽量不要在成员函数中定义静态数据成员,这一点,我们会在下面的C#中,它是明确禁止在成员函数中定义静态成员的。还有就是静态数据成员可以成为成员函数参数的默认值,这是普通数据成员不可以的。

另外C++中,诸如static和extern都是声明性关键字,在实现时往往无需要要有了。

----------------------------------------------------------------------

四、C#时代的static

  既然和C++一样都是面向对象的,那么他们之间会有类似的用法,但C#有自己的特点,那就是:

1.禁止在类的成员函数中定义static数据成员。

2.static可用于修饰类的构造函数(这两点都是跟C++反着做,但也有道理),因为这个构造函数在给定的应用程序域中至多只执行一次,且只有在创建类的实例和引用类的静态成员时才激发静态构造函数,且在一个有静态成员的类中,如果你没有提供显式的静态构造函数,会自动生成。

和C C++相比,C#是全面支持面向对象的,所以一切都是通过类来完成的,故而没有全部变量和局部变量之说,所以C中的那套在这是没有的。

在C#中,static与auto相对应,默认情况下都是auto的,比如:

int value;
string str;
其本质上就是:

auto int value;
auto string str;
而static变量则要显式给出:

static int value;
static string str;

auto的意思就是由程序自动来控制变量的生存周期,用完了就释放,又要用就再分配。static变量则只在第一次使用时分配,以后就都是操作这一个副本了。
总结static在C#中几个用法来说:
1.静态函数成员或静态构造可用于对静态字段和只读字段的初始化工作。
2.被static修饰的成员不能再被访问修饰符修饰,静态成员都是私有的。
3.静态构造函数在整个应用程序域中只执行一次,创建实例或引用该类的任何静态成员时激发静态构造函数,它不可继承亦不可直接调用。
4.静态字段的初始值看文本顺序初始化
5.编译器会对没有显式静态构造函数的类生成一个静态构造函数。