C/C++中的关键字static

12 篇文章 0 订阅

一、static的历史

术语static有着不寻常的历史.起初,在C中引入关键字static是为了表示退出一个块后仍然存在的局部变量。
随后,static在C中有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。为了避免引入新的关键字,所以仍使用static关键字来表示这第二种含义。
最后,C++重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数。

二、static在C/C++中的几种使用方式

具体的设计方式分为面向过程程序设计,面向对象程序设计的static。前者用于普通的全局变量和局部变量,不涉及到类。而后者是主要说在类里的作用。
1.静态全局变量,成为静态全局变量后在其他文件中不可调用。
2.静态局部变量,成为静态局部变量,拥有记忆功能和全局存储权限。
3.静态函数。
面向对象程序设计中:
4.静态数据成员
5.静态成员函数

三、static在C中的作用

举个例子说明static 的作用:
建立一个项目分别创建test.c 和mian.c两个文件

//mian.c中的
int main()
{
    extern  b;
    printf("%d\n",add(1, 2));
    printf("%d\n", b);
    return 0;
}
//test.c中的
int b ;
int add(int a, int b)
{
    return a + b;
}

输出的结果:
这里写图片描述
首先说明extern 是一个申明外部变量。当编译器发现这个关键字修饰的变量不在该文件就回去别的文件查找。
再加入static后编译程序:
这里写图片描述
编译不能通过说明加入static后隐藏了全局变量b 和函数add。
由以上得出结论:
(1)、static修饰具有隐藏属性,没加static的变量和函数在全局都是可见的,加入static后就不能再其他文件访问。
(2)、static修饰变量会改变作用域,把变量放在静态区,其次还能对变量进行初始化为0(在没有显示的初始化时候),全局变量也自动初始化。
(3)、static修饰的数在程序运行结束才回收空间。期间不会销毁。也就是static的持久性。
全局变量、静态全局变量、静态局部变量和局部变量的区别
1.按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。
2.按作用域分, 全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。
3.全局变量(外部变量)的说明之前再冠以static就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。

四、static在面向对象设计中的作用

在面向对象设计 也就是主要对于类而言。static主要加在成员函数,和成员变量前面。成为静态成员函数,静态成员变量。
<1>、静态数据成员

#include<iostream>
using namespace std;
class Test
{public:
    Test()
    {
        _data = 10;
    }
    void Print()
    {
        cout << _data << endl;
    }
    static int count;
private:
    int _data;
};
int Test::count = 0;
int main()
{
    Test t1;
    t1.Print();
    cout <<"sizeof(Test)="<< sizeof(Test)<<endl;
    return 0;
}

注意:
1.使用静态数据成员要注意在类里定义原型。还要在类外初始化一次。
2.对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。也就是说,静态数据成员是该类的所有对象所共有的。
3.对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;
4.因为静态成员在静态区,所以计算类的大小时不加入静态成员的大小。
5.静态数据成员也要遵循pubulic、protected、private的访问限制规则。
6.因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。
<2>、静态成员函数
静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分。普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this是缺省的。如函数fn()实际上是this->fn()。但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。

#include<iostream>
using namespace std;
class Test
{public:
    Test()
    {
        _data = 10;
    }
    void Print()
    {
        cout << _data << endl;
    }
    static int count;
    static void Funtest();
private:
    int _data;
};
int Test::count = 0;
void Test::Funtest()
{
    cout << "static void Funtest()" << endl;
}
int main()
{
    Test::Funtest();
    return 0;
}

总结:
静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数。
非静态成员函数可以任意地访问静态成员函数和静态数据成员。
静态成员函数不能访问非静态成员函数和非静态数据成员。
由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长。
调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使用如下格式:
<类名>::<静态成员函数名>(<参数表>)
调用类的静态成员函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值