谁知道静态成员的纠结心境

来源:互联网 发布:php get class 编辑:程序博客网 时间:2024/05/22 02:14
我们在实际开发的过程中,可能需要某些类的成员变量并不是针对每一个对象的,而是针对每一个类而言的,比如在银行中有一个利率数据,我们希望的是,当一个利率改变的时候,所有的对象都能够看到这个改变的数据,并利用它,而不是每一个对象都有一个利率成员变量。这个时候就设计到了静态成员变量。

一. 内存那些事
静态成员变量是存放在静态全局区(数据段),一个对象改变了其中的静态变量,其他对象的这一变量也都随之改变。
说其是静态变量,个人是这样理解的,该变量不会因为某一次函数调用或者某个对象的销毁而销毁,它是一直存在在静态全局区的。也可以这样理解,它在静态全局区的位置始终没有变过,它是静止不动的,直到整个程序结束掉。

二. C语言中"自私"的static(他人不可见)
static的三个私生子
说static三个私生子,个人的理解是这个样子的,static修饰的变量或者是函数只在当前文件中有用,其他的文件对这些函数或者是变量都是不可见的。
私生子承受了这么大的压力,当然是要给与好处的,对于静态变量如果没有初始化的话,如果这个变量是int类型的,它被初始化为0,如果是字符型的,则被初始化为'\0'。

私生子1--局部变量(私生子中的私生子)
修饰局部变量的时候虽然它的存储方式发生了改变,由原来的栈区放置在了静态全局区,这个时候,他是一直存在着的,但是它的作用域没有改变,就是说它依然在只这个函数里面有效。

私生子1--全局变量
如果是一个普通的全局变量,比如在一个工程中的某个文件中定义的变量在其他的文件中也可以使用,此时只需要加上一个extern就可以使用了,但是这个全局变量加上static之后就不能在其他的文件中使用了。它在其他文件中的可见性就改变了
私生子3--函数
修饰函数的时候和修饰变量的情况差不多,只不过是改变了函数的可见性而已

三. C++中“孤独”的static(没有“对象”的对象)
当我们在类中定义一个静态变量的时候,实际上是声明一个静态变量,拥有静态变量的每个类创建的对象中实际是没有这个静态成员变量的相关的数据的,这个成员变量是存放在静态全局区,所以我们要在类的外面声明这个静态变量在类外定义的时候,要加上类的作用域符号,指定是哪个类的静态成员。
因为静态成员变量不属于任何一个对象,所以我们不能使用类的构造函数进行静态成员变量的初始化,我们必须在类的外部定义并初始化静态成员变量
静态成员函数是没有this指针的,同样的道理,静态函数在只有一个副本,它不属于任何一个对象所拥有。

调用静态成员函数的几种方式
static修饰的变量或者函数只有一个副本,它不属于任何一个对象的,所以这个可以使用对象和类去访问,用类访问的时候需要加上类的作用域
虽然静态成员函数不属于某个对象,使用类的对象、引用和指针来进行访问,还有一种方式是使用类名::函数名进行访问(原因是这个函数也是静态的)。

四. static的死对头--extern
关于extern,我们可以使用extern在一个文件中去访问其他文件中的函数或者是变量,但是这个时候要求如果访问的是变量的话,则要求访问的变量是全局属性的,并且不是静态的,如果这个变量是在一个函数内部的,即是时在main函数的内部也访问不了,因为它不具有全局属性。
我们为什么不使用#include这种方式来调用函数或者是一个变量呢,因为是extern的速度更快
还应该注意的一个问题是,我们经常说的是数组名实际上是一个指针,就是在使用的时候完全可以把它当做一个指针来使用,但是如果我们在一个文件中定义了一个全局数组,比如char arr[] = "hello";然后在另一个 变量中 去使用extern char* arr;,但是这个时候是错误的,因为数组和指针还是有不同 的,这个时候只有声明为extern char arr[];才可以使用。
五. static的好基友--全局变量
总结:其实静态变量和全局变量有很多地方一样,唯一的不同时静态全局变量具有隐藏的属性。


看看静态成员可以帮我们解决什么问题吧
求1+2+3+...+n,要求不能使用乘除法,for,while,if,else,switch,case等关键字以及条件判断语句

    #include <iostream>      using namespace std;            class Temp      {      public:          Temp()          {              ++N;              Sum+=N;          }                static void Reset()          {              N=0;              Sum=0;          }                static int GetSum()          {              return Sum;          }      private:          static int N;          static int Sum;      };            int Temp::N=0;      int Temp::Sum=0;            int solution_Sum(int n)      {          Temp::Reset();                Temp *a=new Temp[n];          delete []a;          a=0;                return Temp::GetSum();      }            int main()      {          cout<<solution_Sum(100)<<endl;          return 0;            }  



解题思路:因为定义了静态成员变量,我们这里定义了对象数组,每次实例化一个对象 的时候,就会改变静态变量,而且是累加的,所以到最后就得到了结果了。























原创粉丝点击