zoukankan      html  css  js  c++  java
  • 关键词:static

    关键词:static
      
    本文是我对C++中关于static(静态类型)的一些理解总结,部分内容摘自《C++ Primer》,错误 不足在所难免,欢迎大家指正^-^
     
    主要内容:

    一. 面向过程程序设计中的static
       1. 全局静态变量
       2. 局部静态变量
       3. 静态函数(可不是静态成员函数哦)

    二. 面向对象程序设计中的static
       1. 静态数据成员
       2. 静态成员函数
     

    一. 面向过程程序设计中的static

    1. 全局静态变量 


       在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。

       1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)

       2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非
    他被显示初始化)


       3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。
      
       看下面关于作用域的程序:
    //testStatic1.cpp
    #include <iostream>
    using namespace std;
      
    void display();
    extern int n;
      
    int main()
    {
      n = 20;
      cout << n << endl;
      display();
      return 0;
    }
      
    //testStatic2.cpp
    #include <iostream>
    using namespace std;
      
    static int n;   //定义全局静态变量,自动初始化为0,仅在本文件中可见

    void display()
    {
      n++;
      cout << n << endl;
    }
     

    文件分别编译通过,但link的时候testStatic1.cpp中的变量n找不到定义,产生错误。
     
    定义全局静态变量的好处:


    <1>不会被其他文件所访问,修改

    <2>其他文件中可以使用相同名字的变量,不会发生冲突。

     

    2 局部静态变量


      在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。

      1)内存中的位置:静态存储区

      2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非
    他被显示初始化)

      3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。

      注:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改
    为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,直到程序结束,只不过我们不能再对他进行访问。


          当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。
     
    3 静态函数
      在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
      函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其

      例如:
    //testStatic1.cpp
    #include <iostream>
    using namespace std;
     
    void display();
    void staticDis();
     
    int main()
    {
      display();
      staticDis();
      renturn 0;
    }
     
    //testStatic2.cpp
    #include <iostream>
    using namespace std;
     
    void display()
    {
      staticDis();
      cout << "display() has been called " << endl;
    }
     
    void staticDis()
    {
      cout << "staticDis() has been called" << endl;
    }
     
    文件分别编译通过,但是连接的时候找不到函数staticDis()的定义,产生错误。
     
    定义静态函数的好处:


    <1> 其他文件中可以定义相同名字的函数,不会发生冲突

    <2> 静态函数不能被其他文件所用。
     

    存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。
     
    auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。


    关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态
    存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。(摘自《C++ Primer》 P337)


    由于static变量的以上特性,可实现一些特定功能。

    1. 统计次数功能


    声明函数的一个局部变量,并设为static类型,作为一个计数器,这样函数每次被调用的时候就可
    以进行计数。这是统计函数被调用次数的最好的办法,因为这个变量是和函数息息相关的,而函数可能在多个不同的地方被调用,所以从调用者的角度来统计比较困难。代码如下:

     
    #include <stdio>
    #include <iostream>
    using namespace std;
     
    void count();


    int main()
    {
     int i;
     for (i = 1; i <= 3; i++)
      count();
      return 0;
    }
     

    void count()
    {
     static num = 0;
     num++;
     cout << " I have been called" << num << "times" << endl;
    }


    输出结果为:
    I have been called 1 times.
    I have been called 2 times.
    I have been called 3 times.
     

    二 面向对象程序设计中的static

     


    1. 静态数据成员

       1) 内存中的位置:静态存储区

       2) 初始化和定义:

           <1> 静态数据成员定义时要分配空间,所以不能在类声明中定义。

           <2> 静态数据成员在程序中只能提供一个定义,所以静态数据成员的初始化不能在类的头文
    件中。

       3)  访问:

           <1> 类对象名.静态数据成员

           <2> 类类型名::静态数据成员
     

       4) 说明:


           a.static数据成员和普通数据成员一样遵public, protected, private 访问规则。

           b.对于非静态数据成员,每个类对象都有自己的拷贝。静态数据成员被当作类的全局对象,
    无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类类型的所有对象共享访问。 

       5) 同全局对象相比,使用静态数据成员有两个优势:

           <1> 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的
    可能性。

           <2> 可以实现信息隐藏。静态成员可以是private成员,而全局对象不能。

       6) 应用:

    class Account {
        Account( double amount, const string &owner );
        String owner() { return _owner ;}
      private:
        static double _interestRate;
        double _amount;
        string _owner;
    };
     

    为什把_interestRate声明为static,而_amount和_owner不呢?
    这是因为每个Account对应不同的主人,有不同数目的钱,而所有Account的利率却是相同的。


    因为在整个程序中只有一个_interestRate数据成员,他被所有Account对象共享,所以把
    _interestRate声明为静态数据成员减少了每个Account所需的存储空间。

    _interestRate值可能变化,所以不能声明为const。因为_interestRate是静态的,所以它只需要
    更新一次我们就可以保证每个Account对象都能访问到更新后的值。要是每个类对象都维持自己的一个拷贝,那么每个拷贝都必须更新,这将导致效率低下和更大的错误可能。

      
      7)静态数据成员的“唯一性”本质(独立于类的任何对象而存在的唯一实例),使他能够以独特
    的方式被使用,这些方式对于非static数据成员来说是非法的。

         <1> 静态数据成员的类型可以是其所属类,而非static数据成员只能被声明为该类对象的指针
    或引用,例如:

     
    class Bar{
      public:
        //...
      private:
        static Bar mem1; //OK
        Bar *mem2;  //OK
        Bar mem3;  //错误
    };
     
         <2> 静态数据成员可以被作为类成员函数的缺省实参,而非static数据成员不可以。例如:
     
    extern int var;
    class Foo {
      private:
        int var;
        static int stcvar;
      public:
        //错误:被解析为非static的Foo:var
        //没有相关的类对象
        int mem1( int = var );
        //OK:解析为static的Foo:stcvar
        //无需相关的类对象
        int mem2( int = stcvar );
        //OK:int var 的全局实例
        int mem3( int = ::var );
    };
     
      8) 类模板的静态数据成员以后讨论^-^
     
    2. 静态成员函数


      1) 声明:在类的成员函数返回值之前加上关键字static,他就被声明为一个静态成员函数。静
    态成员函数不能声明为const或volatile,这与非静态成员函数不同。

      2) 定义:出现在类体外的函数定义不能指定关键字static。

      3) 作用:主要用于对静态数据成员的操作

      4) 静态成员函数与类相联系,不与类的对象相联系。

      5) 静态成员函数不能访问斐静态数据成员。因为非静态数据成员属于特定的类实例。

      6) 静态成员函数没有this指针,因此在静态成员函数中隐式或显示的引用这个指针都将导致编
    译时刻错误。试图访问隐式引用this指针的非静态数据成员也会导致编译时刻错误。

      7) 访问:可以用成员访问操作符(.)和箭头(->)为一个类对象或指向类对象的指针调用静态成员
    函数,也可以用限定修饰符名直接访问或调用静态成员函数,而无需声明类对象。

    他文件所用。

  • 相关阅读:
    Python语言之并发编程
    python语言之系统工具
    python语言之正则
    python语言之字符串与字节
    Python语言之持久化
    Python语言之数字格式化与时间
    Python语言之异常处理与测试
    Java-AQS源码详解(细节很多!)
    redis的主从复制原理
    Amdahl定律和可伸缩性
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1884509.html
Copyright © 2011-2022 走看看