前言

c++ 静态成员变量用static 关键字来声明,是整个类的数据成员,其存储不占用某个具体对象的空间,其存储在静态存储区
c++ 静态成员函数用static 关键字来声明,用于处理静态成员变量,可以用类名来调用,也可以用对象名来调用。

使用静态成员变量的目的:静态成员变量是整个类的数据成员,使用静态成员变量可以实现多个对象共享数据

测试1:

#include <iostream>
using namespace std;class Point{
public:Point(int xx,int yy):x(xx),y(yy){count++;}Point():Point(0,0){}Point(const Point &p);~Point(){count--;}void show(){cout<<x<<" "<<y<<endl;}static void showcount();  //用static来声明静态成员函数
private:int x,y;static int count; //用static来声明静态成员变量
};int Point::count = 0;   //静态成员变量的定义,定义时前面不可以再有static, 且它必须要在类外面来初始化,不能在类内部初始化。静态成员变量在初始化时分配内存。void Point::showcount() {    //静态成员函数的定义,前面不可以再有static,可以在类内部定义,也可以在类外定义。此例为在类外面进行定义。cout<<"count="<<count<<endl;
}Point::Point(const Point &p){  //复制构造函数x = p.x;y = p.y;count++;
}Point fun(Point m){ return m;
}int main(){Point::showcount(); //用     类名::函数名      来调用静态成员函数Point a(1,2);a.show();a.showcount();//也可用    对象名.函数名   来调用静态成员函数Point b(a);b.show();b.showcount();Point c;c.show();c.showcount();Point d = fun(c);d.show();d.showcount();return 0;
}

运行结果:
$ ./a.out
count=0
1 2
count=1
1 2
count=2
0 0
count=3
0 0
count=4


如图,对象a占用8个字节(成员x,y的空间,count不在里面),对象a是局部对象,存放在栈上0x7fffffffdde0的位置处。

count存放在静态存储区的 0x555555756134,不存储在对象中。count属于整个类,不属于某一个具体的对象。
静态成员函数也是一样,属于整个类,不属于某一个对象,所以静态成员函数可以用类名来调用,比如:Point::showcount() 。

static 成员变量必须在类声明的外部初始化,具体形式为:

 type class::name = value;

如本例:int Point::count = 0;
静态成员变量在初始化时不能再加 static,但必须要有数据类型。

static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。没有在类外初始化的 static 成员变量不能使用,因为没分配空间。

测试2:

#include <iostream>
#include <cmath>
using namespace std;class Point{
public:Point(int xx,int yy):x(xx),y(yy){count++;}Point():Point(0,0){}Point(const Point &p);~Point(){count--;}void show(){cout<<x<<" "<<y<<endl;}static void showcount();
public:static int count;   //此例为public属性
private:int x,y;
};int Point::count = 0;void Point::showcount() {cout<<"count="<<count<<endl;
}Point::Point(const Point &p){x = p.x;y = p.y;count++;
}
int main(){Point::showcount();Point a(1,2);cout<<a.count<<endl;  //通过对象a来访问静态成员变量。若count不是public属性,不能用对象来访问,编译时就会报错Point::showcount();Point b(3,4);Point::showcount();return 0;
}

用GDB来查看静态成员变量的存储:

可以看到,当b中count变为2,a中count也变为2,即a和b中的count是共享的。查看a.count和b.count的地址,可以发现是同一个地址,即是同一个存储空间。且这个存储空间是全局存储区(静态存储区),不在对象a和对象b的栈(stack)存储区。
此例中count是public,修改为protected和private,编译报错。

protected:static int count;

private:static int count;


如上图,也就是说,想通过对象来访问静态成员变量,静态成员变量只能是public属性。这一点和对象去访问普通的成员变量一样。类外面,对象只能访问public成员变量,不能访问protected和private的成员变量。

测试3:

void Point::showcount() {cout<<"count="<<count<<endl;cout<<x<<endl; //新增,尝试在静态成员函数中去访问普通的成员变量,编译报错。
}


也即是说,在静态成员函数中,不能去访问普通的成员变量。原因是没有this指针,不知道普通成员变量x放在哪里。
原因分析:
编译器在编译一个普通成员函数时,会隐式地增加一个形参 this,并把当前对象的地址赋值给 this,所以普通成员函数只能在创建对象之后通过对象来调用,因为它需要当前对象的地址。也即是有了对象,才有对象的this指针,没有对象,就无法调用普通成员函数。由于类没有this指针,所以不能用类名去调用普通成员函数,只能用实际的对象去调用普通成员函数

而静态成员函数可以通过类来直接调用,编译器不会为它增加形参 this,它不需要当前对象的地址,所以不管有没有创建对象,都可以调用静态成员函数。因为静态成员函数要访问的是静态成员变量(存储在全局存储区,和this指针没毛关系)。
由于静态成员函数没有 this 指针,不知道指向哪个对象,无法访问对象的成员变量,所以静态成员函数不能访问普通成员变量,只能访问静态成员变量

总结:

  1. 一个类中可以有一个或多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它。注意,是共享,共享,共享,也即是只会占同一份静态存储空间
  2. static 成员变量和普通 static 变量一样,都在内存分区中的全局数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。根本原因是静态成员变量和对象的存储空间不同,是在不同的时期去分配的
  3. 静态成员变量必须初始化,而且只能在类体外进行。例如:
    int Point::count = 0;
    初始化时可以赋初值,也可以不赋值。如果不赋值,那么会被默认初始化为 0
    全局数据区的变量都有默认的初始值 0,而**动态数据区(堆区、栈区)**变量的默认值是不确定的,一般认为是垃圾值。
  4. 静态成员变量既可以通过对象名访问,也可以通过类名访问,但要遵循 private、protected 和 public 关键字的访问权限限制。
    当在类外面通过对象名访问时,静态成员变量属性必须是public,对于不同的对象时,访问的是同一份内存(本质是共享)。
  5. 静态成员函数在声明时要加 static,在定义时不能加 static 。静态成员函数只能访问静态成员变量,去访问普通成员变量,编译就报错。

c++ ——静态成员变量和静态成员函数相关推荐

  1. C++静态成员变量和成员函数

    静态成员变量和成员函数 简介 sizeof不将静态成员变量的大小计算在内 可以通过类名来访问静态成员 静态成员函数不能访问类的非静态成员 简介 static加在局部变量的前面改变其存储类型使之成为静态 ...

  2. c++中静态成员变量和静态成员函数

    静态成员变量 在一个类中,若将一个成员变量声明为static,这种成员成为静态成员变量,与一般的数据成员不同,无论建立了多少个对象,都只想有一个静态数据的拷贝,静态成员变量,属于某个类,所有对象共享 ...

  3. 13.C++-静态成员变量、静态成员函数

    首先回顾下成员变量 能通过对象名能够访问public成员变量 每个对象的成员变量都是专属的 成员变量不能在对象之间共享 再来讲讲类的静态成员变量 介绍 静态成员变量属于整个类所有 静态成员变量的生命期 ...

  4. C++面试题-面向对象-静态成员变量以及静态成员函数

    C++面试题-面向对象-静态成员变量以及静态成员函数 问:在类中,静态数据成员和普通数据成员有何区别? 答: 普通数据成员属于类的对象,对象被创建后,普通数据成员才会分配内存.静态数据成员属于整个类, ...

  5. C++静态成员变量与静态成员函数

    类的静态成员有两种:静态成员变量和静态成员函数,语法是在普通成员变量和成员函数前加static关键字. 0.定义 class CRect{ public:void show();//普通成员函数sta ...

  6. C++的静态成员变量和静态成员函数

    C++的静态成员变量和静态成员函数 静态成员变量和静态成员函数算是C++面向对象编程中的一个重点和难点,这里的静态具体指什么呢?与普通的成员变量和成员函数相比,静态成员函数和静态成员变量是属于类的,而 ...

  7. 静态成员变量和静态成员函数

    静态成员变量 一个类中可以有一个或多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它. static 成员变量和普通 static 变量一样,都在内存分区中的全局数据区分配内存,到程序结 ...

  8. 类中的静态成员变量和静态成员函数

    static静态成员函数 1.static 修饰成员变量 2.static修饰静态成员函数 引子: 静态成员函数: 注意: 3.const 修饰静态成员 静态成员案例 案例1:静态成员 统计类 实例化 ...

  9. qt 静态成员变量_Qt 静态成员函数的调用非静态成员变量,非静态成员函数

    在多人开发的项目中,一些通用的工具类接口可以用静态成员函数.方便调用,并且不容易调用错误. 静态成员函数不传递this指针(不能->),不识别对象个体,所以经常用于对静态数据成员进行操作.不能操 ...

最新文章

  1. ui和android有联系,Android单位换算与UI适配
  2. 三级数据库还是linux好,08年计算机三级数据库辅导:如何修改Linux下MySQL5.0的默认连接数...
  3. Kubernetes Service(溪恒)
  4. [BOI2007] Mokia
  5. python中的文件备份过程
  6. mysql报错 DuplicateKeyException分析与解决
  7. SpringBoot和Elasticsearch集成
  8. mysql执行脚本的方法
  9. 移动互联网实战--资源类APP的数据存储处理和优化
  10. 【Unity】 NGUI学习笔记(二)NGUI基础功能
  11. SpringBoot项目实现敏感词汇过滤
  12. 微信公众号在线答题小程序系统怎么做答题游戏活动
  13. 游戏修改器制作教程五:OllyDBG和其他调试工具
  14. 分享一种快速制作二维码标签及防伪溯源二维码的方法
  15. 计算机软件对英语,计算机软件英语论文
  16. JAVA复制数组的三种方法
  17. 自动化网络安全防御的问题
  18. python-InputWhile基础知识
  19. oracle exportdmp,Oracle导入导出dmp表
  20. 编程实践精华总结集锦系列2: SpringBoot/Maven/IDEA/Java/Kotlin/Redis等等

热门文章

  1. Django制作blog界面
  2. Error creating bean with name ‘marketCluesController‘: Unsatisfied dependency expressed through fiel
  3. Cocos Creator TypeScript 中使用ProtoBuf(利用工具把proto文件生成对应的js文件以及ts文件)
  4. 动态阈值_传感器的动态和静态区别是什么
  5. 【应急案例】Linux应急记录
  6. 解霸把MTV歌曲转换为MP3
  7. 基于java jsp的在线答疑网站系统Struts框架
  8. spring+springMVC+配置文件propertites
  9. 计算机怎样连接硬盘,台式机硬盘如何接笔记本【方法步骤】
  10. 下月起,即将影响千万人的大事