• C++之static


         

    目录

    一、静态属性

     总结:

    二、静态方法

    例题:


       由关键字static修饰类中成员,成为类的静态成员。类的静态成员为其所有对象共享,不管有多少对象,静态成员只有一份存于公用内存中。静态数据成员被当做该类类型的全局对象。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化。

    一、静态属性

            在类的设计中,用关键字static修饰的数据成员为静态数据成员。有该类型实例化的所有对象,共享系统为静态成员分配一个存储空间。而这个存储空间是程序执行main函数之前分配的,在实例化对象不再为静态成员分配空间(静态成员数据不再对象空间中)

    1、设计静态数据成员的目的是信息共享,只会被初始化一次,于实例无关

    示例:

    1. class Circle {
    2. private:
    3. static double pi;
    4. double rid;
    5. public:
    6. Circle(double r=0.0):rid(r){}
    7. ~Circle(){}
    8. double area()const
    9. {
    10. return pi * rid * rid;
    11. }
    12. };
    13. double Circle:: pi=3.14;
    14. int main()
    15. {
    16. cout << sizeof(Circle) << endl;
    17. Circle cir(12.23);
    18. size_t sz = sizeof(cir);
    19. cout << sz << endl;
    20. return 0;
    21. }

     也就是说 static 并不占用Cricle的内存空间(栈区),他在全局数据区分配内存

    注意:

            与全局变量相比,使用静态数据成员有两个优势:

    1. 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性
    2. 可以实现信息隐藏,静态成员可以是private,而全局变量不能 

     2、静态数据是该类所有对象所共有的,可以提供同一类型的所有对象之间,信息共享或信息交换的一种方式

            静态数据成员属于整个类型,使用时可以用以下格式:

            类名::静态数据成员名或者 对象.静态数据成员名(前提是可以访问符为public)

    示例:

    1. #include
    2. using namespace std;
    3. class Box
    4. {
    5. public:
    6. static int objectCount;
    7. // 构造函数定义
    8. Box(double l=2.0, double b=2.0, double h=2.0)
    9. {
    10. cout <<"Constructor called." << endl;
    11. length = l;
    12. breadth = b;
    13. height = h;
    14. // 每次创建对象时增加 1
    15. objectCount++;
    16. }
    17. double Volume()
    18. {
    19. return length * breadth * height;
    20. }
    21. private:
    22. double length; // 长度
    23. double breadth; // 宽度
    24. double height; // 高度
    25. };
    26. // 初始化类 Box 的静态成员
    27. int Box::objectCount = 0;
    28. int main(void)
    29. {
    30. Box Box1(3.3, 1.2, 1.5); // 声明 box1
    31. Box Box2(8.5, 6.0, 2.0); // 声明 box2
    32. // 输出对象的总数
    33. cout << "Total objects: " << Box::objectCount << endl;
    34. return 0;
    35. }

    输出结果:

    1. Constructor called.
    2. Constructor called.
    3. Total objects: 2

    3、在类的成员函数中使用静态数据成员,静态数据成员没有this指针,this指针指向类的对象本身,而static静态成员函数不依赖对象调用,它不与任何的对象相联系,所以当然不需要this指针。

    4、静态属性的类型是int,short,char等整型,并且是const,可以在类中直接初始化

     总结:

    1. 设计静态数据成员目的是信息共享,和信息交流
    2. 类的静态数据成员为所有类对象所共享,不属于某个具体的实例
    3. 类的静态数据成员必须在类外定义,定义时不添加static关键字,不能在构造函数的初始化列表中创建
    4. 类的静态数据成员类型是int,short,char ,longlong,并且是const,可以在类中直接初始化也可以在类外初始化
    5. 在类的成员函数中使用静态数据成员,静态数据成员之前没有this
    6. 当类的静态数据成员为公有时,可以在外部函数使用:类名::静态数据成员名或者对象.静态数据成员名
    7. 可以在类体中定义自身的静态类型对象

    二、静态方法

    1. 如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
    2. 静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数。
    3. 静态成员函数有一个类范围,他们不能访问类的 this 指针。可以使用静态成员函数来判断类的某些对象是否已被创建。

    注意:

            静态成员函数没有this指针,因此在静态成员函数显式的使用this指针都将会导致编译时刻错误,试图访问隐式使用this指针所指向的非静态数据成员也会导致编译时刻错误

    静态成员函数与普通成员函数的区别:

    • 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
    • 普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针。

    示例: 

    1. #include
    2. using namespace std;
    3. class Box
    4. {
    5. public:
    6. static int objectCount;
    7. // 构造函数定义
    8. Box(double l=2.0, double b=2.0, double h=2.0)
    9. {
    10. cout <<"Constructor called." << endl;
    11. length = l;
    12. breadth = b;
    13. height = h;
    14. // 每次创建对象时增加 1
    15. objectCount++;
    16. }
    17. double Volume()
    18. {
    19. return length * breadth * height;
    20. }
    21. static int getCount()
    22. {
    23. return objectCount;
    24. }
    25. private:
    26. double length; // 长度
    27. double breadth; // 宽度
    28. double height; // 高度
    29. };
    30. // 初始化类 Box 的静态成员
    31. int Box::objectCount = 0;
    32. int main(void)
    33. {
    34. // 在创建对象之前输出对象的总数
    35. cout << "Inital Stage Count: " << Box::getCount() << endl;
    36. Box Box1(3.3, 1.2, 1.5); // 声明 box1
    37. Box Box2(8.5, 6.0, 2.0); // 声明 box2
    38. // 在创建对象之后输出对象的总数
    39. cout << "Final Stage Count: " << Box::getCount() << endl;
    40. return 0;
    41. }

    编译结果:

    1. Inital Stage Count: 0
    2. Constructor called.
    3. Constructor called.
    4. Final Stage Count: 2

    例题:

    不能使用if,循环,公式,求n的累加

    1. //使用静态数据成员,调用n次构造函数,产生n次累加
    2. class ADD
    3. {
    4. private:
    5. static int a;
    6. static int b;
    7. public:
    8. ADD() {
    9. a += b;
    10. b++;
    11. };
    12. int Getnumber()
    13. {
    14. return a;
    15. }
    16. };
    17. int ADD:: a=0;
    18. int ADD::b=1;
    19. //三目运算符求解
    20. int ADD1(int n)
    21. {
    22. return n == 1 ? 1 : ADD1(n - 1) + n;
    23. }
    24. int main()
    25. {
    26. ADD* x = new ADD[100];
    27. cout << x->Getnumber() << endl;
    28. cout << ADD1(100) << endl;
    29. return 0;
    30. }

    为什么static成员函数不能是const?

    静态成员函数是属于某个类的,而不是某个对象。所以在类被定义的时候,在对象被定义之前就已经存在了,所以显然也可以看出他不是某个对象,但是const是用来修饰对象的,使对象保持不变,里面的数据成员保持不变,那么对于不是对象的static函数,就不可以用const修饰了。函数中的const其实就是用来修饰this指针的,意味this指向的内容不可变,static成员函数没有this,就不能使用const

  • 相关阅读:
    基于keras的疫情预测模型的设计与实现
    Windows环境变量 和 Linux环境变量
    ECharts的配置(一)
    Jmeter接口自动化(七)后置处理器
    图解 | 聊聊 MyBatis 缓存
    海外监管机构出手制裁DeFi,去中心化成伪命题了吗?波卡将何去何从?
    Python函数中的可变长度参数:*args和**kwargs
    搭建集群版 Eureka Server 服务注册中心
    项目介绍:开源安防摄像机(嵌入式软件)
    9月大型语言模型研究论文总结
  • 原文地址:https://blog.csdn.net/weixin_51609435/article/details/125857070