05-- C++ 类的静态成员详细讲解

时间:2022-03-01 07:27:24
 
 在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。

静态成员的定义或声明要加个关键static。静态成员可以通过双冒号来使用即<类名>::<静态成员名>。

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象。希望阅读本文可以使读者对类的静态成员变量和成员函数有更为深刻的认识。

第一个例子,通过类名调用静态成员函数和非静态成员函数

  1. class Point
  2. {
  3. public:
  4. void init()
  5. {
  6. }
  7. static void output()
  8. {
  9. }
  10. };
  11. void main()
  12. {
  13. Point::init();
  14. Point::output();
  15. }

编译出错:error C2352: 'Point::init' : illegal call of non-static member function

结论1:不能通过类名来调用类的非静态成员函数。

第二个例子,通过类的对象调用静态成员函数和非静态成员函数

将上例的main()改为:

  1. void main()
  2. {
  3. Point pt;
  4. pt.init();
  5. pt.output();
  6. }

编译通过。

结论2:类的对象可以使用静态成员函数和非静态成员函数。

第三个例子,在类的静态成员函数中使用类的非静态成员

  1. #include <stdio.h>
  2. class Point
  3. {
  4. public:
  5. void init()
  6. {
  7. }
  8. static void output()
  9. {
  10. printf("%d\n", m_x);
  11. }
  12. private:
  13. int m_x;
  14. };
  15. void main()
  16. {
  17. Point pt;
  18. pt.output();
  19. }

编译出错:error C2597: illegal reference to data member 'Point::m_x' in a static member function

因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以这个调用就出错了,就好比没有声明一个变量却提前使用它一样。

结论3:静态成员函数中不能引用非静态成员。

第四个例子,在类的非静态成员函数中使用类的静态成员

  1. class Point
  2. {
  3. public:
  4. void init()
  5. {
  6. output();
  7. }
  8. static void output()
  9. {
  10. }
  11. };
  12. void main()
  13. {
  14. Point pt;
  15. pt.output();
  16. }

编译通过。

结论4:类的非静态成员函数可以调用用静态成员函数,但反之不能。

第五个例子,使用类的静态成员变量

  1. #include <stdio.h>
  2. class Point
  3. {
  4. public:
  5. Point()
  6. {
  7. m_nPointCount++;
  8. }
  9. ~Point()
  10. {
  11. m_nPointCount--;
  12. }
  13. static void output()
  14. {
  15. printf("%d\n", m_nPointCount);
  16. }
  17. private:
  18. static int m_nPointCount;
  19. };
  20. void main()
  21. {
  22. Point pt;
  23. pt.output();
  24. }

按Ctrl+F7编译无错误,按F7生成EXE程序时报链接错误

error LNK2001: unresolved external symbol "private: static int Point::m_nPointCount" (?m_nPointCount@Point@@0HA)

这是因为类的静态成员变量在使用前必须先初始化。

在main()函数前加上int Point::m_nPointCount = 0;

再编译链接无错误,运行程序将输出1。

结论5:类的静态成员变量必须先初始化再使用。

结合上面的五个例子,对类的静态成员变量和成员函数作个总结:

一。静态成员函数中不能调用非静态成员。

二。非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。

三。静态成员变量使用前必须先初始化(如int MyClass::m_nNumber = 0;),否则会在linker时出错。

再给一个利用类的静态成员变量和函数的例子以加深理解,这个例子建立一个学生类,每个学生类的对象将组成一个双向链表,用一个静态成员变量记录这个双向链表的表头,一个静态成员函数输出这个双向链表。

  1. #include <stdio.h>
  2. #include <string.h>
  3. const int MAX_NAME_SIZE = 30;
  4. class Student
  5. {
  6. public:
  7. Student(char *pszName);
  8. ~Student();
  9. public:
  10. static void PrintfAllStudents();
  11. private:
  12. char    m_name[MAX_NAME_SIZE];
  13. Student *next;
  14. Student *prev;
  15. static Student *m_head;
  16. };
  17. Student::Student(char *pszName)
  18. {
  19. strcpy(this->m_name, pszName);
  20. //建立双向链表,新数据从链表头部插入。
  21. this->next = m_head;
  22. this->prev = NULL;
  23. if (m_head != NULL)
  24. m_head->prev = this;
  25. m_head = this;
  26. }
  27. Student::~Student ()//析构过程就是节点的脱离过程
  28. {
  29. if (this == m_head) //该节点就是头节点。
  30. {
  31. m_head = this->next;
  32. }
  33. else
  34. {
  35. this->prev->next = this->next;
  36. this->next->prev = this->prev;
  37. }
  38. }
  39. void Student::PrintfAllStudents()
  40. {
  41. for (Student *p = m_head; p != NULL; p = p->next)
  42. printf("%s\n", p->m_name);
  43. }
  44. Student* Student::m_head = NULL;
  45. void main()
  46. {
  47. Student studentA("AAA");
  48. Student studentB("BBB");
  49. Student studentC("CCC");
  50. Student studentD("DDD");
  51. Student student("MoreWindows");
  52. Student::PrintfAllStudents();
  53. }

程序将输出:

05-- C++ 类的静态成员详细讲解

当然在本例还可以增加个静态成员变量来表示链表中学生个数,如果读者有兴趣,就将这个作为小练习吧。

转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/6721430

05-- C++ 类的静态成员详细讲解的更多相关文章

  1. 面向对象课后深入学习(C&plus;&plus; 类的静态成员详细讲解)

    今天在刚申请了博客,一下午都在写那个随笔,所以说好的来看c++的也放在了最后,下星期就考试了,这个类的静态成员是我不是很懂的,在网上 看到一片很详细的博客考下来回去慢慢看. 在C++中,静态成员是属于 ...

  2. C&plus;&plus; 类的静态成员详细讲解

    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...

  3. C&plus;&plus; 类的静态成员详细讲解(转)

    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...

  4. C&plus;&plus; 类的静态成员详细讲解&lbrack;转&rsqb;

    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...

  5. 转:C&plus;&plus; 类的静态成员详细讲解

    在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...

  6. 简单Java类 全网最详细讲解 &excl;&excl;&excl;

    最近学习java非常吃力,学习的进度很快,由于基础没打牢固,整体上项目理解很吃力,偶尔会遇到一些基本的概念,都会阻碍整体的理解.最近也看了不少的视频讲解,听得很迷,最后搞得很乱,没有明确的学习目标,今 ...

  7. 【Cocos2d-X开发学习笔记】第12期:动作类CCAction的详细讲解

    一般对于游戏中的精灵而言,它们不仅仅是存在于场景中,而且是动态展现的,例如,精灵移动的动态效果.动 画效果.跳动效果.闪烁和旋转动态效果等.每一种效果都可以看成是精灵的一个动作. 一.动作类(CCAc ...

  8. &lbrack;VC&plus;&plus;&rsqb;用CTime类得到当前日期、时间、星期,格式化&lpar;详细讲解&rpar;

    用CTime类得到当前日期.时间.星期,格式化(详细讲解)2009/05/12 09:48 A.M.① 定义一个CTime类对象 CTime time; ② 得到当前时间 time = CTime:: ...

  9. 第四节:详细讲解Java中的类和面向对象思想

    前言 大家好,给大家带来详细讲解Java中的类和面向对象思想的概述,希望你们喜欢 类和面向对象 在Java中怎样理解对象,创建对象和引用:什么是引用,对于基础学习的同学,要深入了解引用.示例:Stri ...

随机推荐

  1. Atitit cnchar simp best list &&num;160&semi;汉字简化方案 最简化汉字256个

    Atitit cnchar simp best list  汉字简化方案 最简化汉字256个 1.1. 最简化发音1 1.2. 根据笔画密度,删除了密度高的字..1 1.3. 使用同发音的英文字母等代 ...

  2. 67&period; 总结篇:面试中随机数&quot&semi;等概率&quot&semi;vs&quot&semi;不等概率&quot&semi;生成问题&lbrack;random generator with equal or unequal probability&rsqb;

    [本文链接] http://www.cnblogs.com/hellogiser/p/random-generator-with-equal-or-unequal-probability.html 1 ...

  3. Miller-Rabin质数测试

    Miller-Rabin质数测试 本文主要讨论使用Miller-Rabin算法编写素数的判定算法,题目来源于hihocoder. 题目 题目要求 时间限制:10000ms 单点时限:1000ms 内存 ...

  4. Qt&colon; 网络编程之UDP(理论&plus;实例)

    http://blog.csdn.net/rl529014/article/details/52888525

  5. 像web一样使用python

    使用传统的web开发技术,也就是html+js,然后搭配一个后端语言,已经成为当今web开发的固定模式了,为此也形成了众多的toolkit,譬如ror,django,各种js图形库更是玲琅满目,从非常 ...

  6. js正则之零宽断言

    我们学到的正则表达式匹配,都是有“宽度”的,使用 \w+. 匹配下面文本,会将 . 一同匹配: regular. expression. 如果不想匹配符号,只匹配一个位置,就要用到“零宽断言”(匹配宽 ...

  7. vscode C&plus;&plus;开发环境配置教程&lpar;教你如何用vscode写C&plus;&plus;&rpar;

    用了一段时间的cb,Devc++,但一直感觉cb的高亮太差,而Devc++使用体验差(尤其是代码补全功能),换过vs2017,但是由于其太大了,卡顿十分明显,所以最终选择了vscode这款轻量级编译器 ...

  8. 枚举进行位运算 枚举组合z

    枚举进行位运算--枚举组合 public enum MyEnum { MyEnum1 = , //0x1 MyEnum2 = << , //0x2 MyEnum3 = << , ...

  9. Linux命令之rpm安装命令

    在 Linux 操作系统下,几乎所有的软件均通过RPM 进行安装.卸载及管理等操作.RPM 的全称为Redhat Package Manager ,是由Redhat 公司提出的,用于管理Linux 下 ...

  10. DtCMS 在IIS7&period;0 下之伪静态

    1)首先新建一个应用程序池,名称任意,比如:nettest,托管管道模式先暂时设置为集成模式,等下面的一系列设置完成之后再设置成经典模式: 2)部署好站点,并将此站点的应用程序池设置为nettest; ...