在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. }

程序将输出:

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

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

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

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

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

  2. C++ 类的静态成员详细讲解

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

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

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

  4. C++ 类的静态成员详细讲解[转]

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

  5. 转:C++ 类的静态成员详细讲解

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

  6. 简单Java类 全网最详细讲解 !!!

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

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

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

  8. [VC++]用CTime类得到当前日期、时间、星期,格式化(详细讲解)

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

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

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

随机推荐

  1. 基于Ubuntu系统的Tomcat部署项目

    第一步.拿到项目war包 第二步.上传到服务器/var/lib/tomcat8/webapps/ROOT目录下 第三步.使用命令解压war包 jar -xvf star1.0.0.war 第三步.重启 ...

  2. AndroidTreeView:Android树形节点View

     AndroidTreeView:Android树形节点View AndroidTreeView是github上的一个第三方开源项目,其在github上的项目主页是:https://github. ...

  3. HBase行键的设计

    rowkey是行的主键,而且hbase只能用rowkey范围即scan来查找数据.rowkey是以字典排序的.可以巧妙设计行键,比如想通过电影的评价进行排序,可以把评分rate和电影id组合起来,ra ...

  4. nyoj_216_A problem is easy_201312051117

    A  problem is easy 时间限制:1000 ms  |           内存限制:65535 KB 难度:3   描述 When Teddy was a child , he was ...

  5. 【ACM】hdu_zs3_1008_Train Problem I_201308100835

    Train Problem I Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)Tota ...

  6. C#--正则匹配

    一个好用的Regex测试插件 快捷键:ctrl+ r , ctrl+ x 打开正则表达式工具 C#的正则表达式的常用的规则: [abc] 里面的每一次字符都可以进行匹配 a{2} 匹配2个a a{2, ...

  7. Android学习之6.0系统执行时权限设置

    今天讲讲工作中遇见的6.0运行时权限处理问题.起因就是设置版本号更新时,在6.0系统会报错,起因就是6.0动态权限设置,由于在google为了安全考虑,对于一些特定权限会征询客户授权,这当然会大大添加 ...

  8. 天了噜,我国4G用户超过2亿了!

    近期,看到工信部一组统计数据,小编整个人都不好了,数据显示,2015年5月我国4G用户净增2281.6万,总数超过2亿户. 没错,卡是换成了4G卡,还是那句话,然并卵,用的还是3G手机.开的还是2G网 ...

  9. Yum重装走过的坑

    今天因为用yum方式安装mongo遇到报错,从而我选择卸载yum并重新安装. 我先选择了用rpm方式进行重装,从163的packages列表里面找到64位redhat6.5可以用的三个rpm包,安装过 ...

  10. 【Android】ListView 优化

    重用 ListView Item ListView创建时其会创建屏幕可容纳数量的 Item.ListView 滚动时,刚消失的 item 会被保存到回收池中.新出现的 item 从回收池中获取避免反复 ...