zoukankan      html  css  js  c++  java
  • C++ static 静态变量&静态成员函数

     .h文件中定义
    static变量后,如 static QTcpSocket * socket;

    那么一定要在.cpp中

    构造函数的外面将其初始化为

    QTcpSocket * Cfiletransfer::m_socket = NULL;

    否则会报错:如无法识别的外部变量。。。

    # include <iostream>

    using namespace std;
    typedef struct
    {
        int Index;
        char str[256];
    } stArr;
    class Base
    {
    private:
        static stArr arr;
    public:
        static void Print();
    };
    stArr Base::arr = { 0, "a" };  // 静态成员变量需要在类外部定义,且需要初始化
    void Base::Print()
    {
        cout << arr.str[arr.Index] << endl;
    }
    int main()
    {
        Base base;
        base.Print();
        return 0;
    }

    简单概括以下:

    1.static 改变变量的存储方式和生命周期;

    2.限制成员变量的访问域,static定义后变量只能在本文件中使用。

    3.····

     
     
     
    静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值。
       静态成员的值对所有的对象是一样的。静态成员可以被初始化,但只能在类体外进行初始化。
    一般形式:
        数据类型类名::静态数据成员名=初值
        注意:不能用参数初始化表对静态成员初始化。一般系统缺省初始为0。

    关于静态成员函数,可以总结为以下几点:
    出现在类体外的函数定义不能指定关键字static;
    静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
    非静态成员函数可以任意地访问静态成员函数和静态数据成员;
    静态成员函数不能访问非静态成员函数和非静态数据成员;
    由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
    调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,
    当同一类的所有对象使用一个量时,对于这个共用的量,可以用静态数据成员变量,这个变量对于同一类的所有的对象都取相同的值。静态成员变量只能被静态成员函数调用。静态成员函数也是由同一类中的所有对象共用。只能调用静态成员变量和静态成员函数。

     

    static的用法:

    static在C语言中的用法有两方面:

    1. 修饰函数以及全局变量, 使被修饰的对象的可见性仅限于被定义的文件中

    // calNum.cpp
    static int num = 10;
    static int calNum(int );  
    //可见性均只限于calNum.cpp, 在其他文件中不可见
    • 1

    上述static的用法在C代码中比较常见,但是在C++代码中,我们可以用更加有效的方法替代, 那就是无名namesapce, 既然namespace没有名字, 你在其他文件当然是无法访问的,也就是说无名namespace的作用域只能在定义文件内。代码如下:

    namespace {
        int number = 10;
    
        int calNum(int num) { return num+1;}
    };
    
    int main()
    {
        number = 11;  
    
        int newNum = calNum(number);
    
        return 0;
    }


    2.修饰local变量

    static修饰local变量,使得local变量的生命周期上升到跟全局变量一样,但是不会改变local变量的作用域。 static修饰的local变量会被存储在全局变量/静态变量区内, 而不是在栈中。

    int calTimes(void )
    {
        static int times = 0;
        return  ++times;
    }
    
    int num1 = calTImes();  // 1
    int num2 = calTimes();  // 2

    3. 修饰类成员变量以及成员函数

    在c++中,static新增的用法是修饰成员变量以及成员函数。 static修饰的成员变量是隶属于整个类别所有成员所共享, 不是仅仅属于某一个类对象。static修饰的成员函数不能操作非static成员变量。这是因为普通成员函数会有个默认的形参为this指针, this指针所指向对象为具体的某个类对象, static修饰的成员函数不存在this指针。

    class textBook {
    public:
        static int getNum() {return num;}  //right
        static int getNum1() {return num1;}  //Error
    private:
        int num1;
        static int num;
    };

    以下是举例

    static在c里面可以用来修饰变量,也可以用来修饰函数。
    先看用来修饰变量的时候。变量在c里面可分为存在全局数据区、栈和堆里。其实我们平时所说的堆栈是栈而不是堆,不要弄混。
    int a ;
    int main()
    {
        int b ; 
        int c* = (int *)malloc(sizeof(int));
    }
    a是全局变量,b是栈变量,c是堆变量。
    static对全局变量的修饰,可以认为是限制了只能是本文件引用此变量。有的程序是由好多.c文件构成。彼此可以互相引用变量,但加入static修饰之后,只能被本文件中函数引用此变量。
    static对栈变量的修饰,可以认为栈变量的生命周期延长到程序执行结束时。一般来说,栈变量的生命周期由OS管理,在退栈的过程中,栈变量的生命也就结束了。但加入static修饰之后,变量已经不再存储在栈中,而是和全局变量一起存储。同时,离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。
    static对函数的修饰与对全局变量的修饰相似,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。

    文件a.c
    static int i; //只在a文件中用
    int j;          //在工程里用
    static void init()         //只在a文件中用
    {
    }
    void callme()          //在工程中用
    {
        static int sum;
    }

    上面的全局i变量和init()函数只能用在a.c文件中,局部变量sum的作用域只在callme里。变量j和函数callme()的全局限扩充到整个工程文件。所以可以在下面的b.c中用extern关键字调用。extern告诉编译器这个变量或者函数在其他文件里已经被定义了。

    文件b.c
    extern int j;                    //调用a文件里的
    extern void callme();   //调用a文件里的
    int main()
    {
      ...
    }

    extern的另外用法是当C和C++混合编程时如果c++调用的是c源文件定义的函数或者变量,那么要加extern来告诉编译器用c方式命名函数:

    文件A.cpp调用a.c里面的变量i和函数callme()
    extern "C"  //在c++文件里调用c文件中的变量
    {
       int j;
       void callme();
    }
    int main()
    {
       callme();
    }

    二 static法则:

    A、若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
    B、若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
    C、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;

    全局变量有外部、静态两种存储方式。
    (1)全局变量一般用外部存储方式存储,用保留字extern加以定义。此时,变量的作用域是构成整个程序的所有程序文件,也就是定义的外部变量可供其它程序文件使用。
    使用这样的全局变量一定要非常慎重,一旦产生错误,将波及整个程序。
    (2)如果希望全局变量仅限于本程序文件使用,而其它程序文件中不能引用,这时必须将其存储方式定义为静态存储方式,用保留字static加以定义。此时称为静态外部变量。
    例如,在上例文件filel.c中,如果作这样的定义:
    static int a:
    则变量a的作用域被缩小至本程序文件filel.c,文件file2.c中不能引用。
    值得注意的是对全局变量加static,定义为静态存储方式,并不意味着是静态存储;而不加static,是动态存储。两种形式的全局变量(外部变量)都是静态存储方式,都是编译时分配存储空间,但作用域不同。使用静态外部变量,有利于隔离错误,有利于模块化程序设计。
    (3)全局变量的缺省存储方式是外部存储方式。
    前面章节中的程序没有见到变量的存储类别定义,实际上采用变量的缺省存储方式。对局部变量采用auto方式,对全局变量采用extern方式。这也是至今为止,我们在程序中没有见到auto、extern等的原因。
    至此,我们对变量的存储类别及数据类型进行了全面讨论,在此作个小结。
    1.变量定义的一般形式
    存储类别数据类型变量表;
    2.变量定义的作用
    ①规定了变量的取值范围。
    ②规定了变量进行的运行操作。
    ③规定了变量的作用域。
    ④规定了变量的存储方式。
    ⑤规定了变量占用的存储空间。
    3.局部变量和全局变量
    从作用域角度将变量分为局部变量和全局变量。它们采取的存储类别如下:
    局部变量:
    ①自动变量,即动态局部变量(离开函数,值就消失)。
    ②静态局部变量(离开函数,值仍保留)。
    ③寄存器变量(离开函数,值就消失)。
    ④形式参数可以定义为自动变量或寄存器变量。
    全局变量:
    ①静态外部变量(只限本程序文件使用)。
    ②外部变量(即非静态的外部变量,允许其它程序文件引用)。
    4.动态存储和静态存储
    从变量存在时间可将变量存储分为动态存储和静态存储。静态存储是在整个程序运行时都存在,而动态存储则是在调用函数时临时分配存储单元。
    动态存储:
    ①自动变量(函数内有效)。
    ②寄存器变量(函数内有效)。
    ③形式参数。
    静态存储:
    ①静态局部变量(函数内有效)。
    ②静态外部变量(本程序文件内有效)。
    ③外部变量(整个程序可引用)。
    5.静态存储区和动态存储区
    从变量值存放的位置可将变量存储区分为静态存储区和动态存储区:
    内存中静态存储区:
    ①静态局部变量。
    ②静态外部变量。
    ③外部变量(可被同一程序其它文件引用)。
    内存中动态存储区:自动变量和形式参数。
    CPU中的寄存器:寄存器变量。

  • 相关阅读:
    侧边框伸缩
    百度登录界面
    PHP 判断是否包含在某个字符串中
    三个等于号===和两个等于号==的区别
    PHP的魔法方法
    Apache和PHP环境配置
    群同构与线性空间同构的区别
    SciPy0.11.0(or higher)安装
    博客搬家
    简单的组件传值
  • 原文地址:https://www.cnblogs.com/ruoke9/p/5832165.html
Copyright © 2011-2022 走看看