在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. ansible ad-hoc 参考

    # 检查主机连接 # ansible test -m ping # 执行远程命令 # ansible test -m command -a 'uptime' # 执行主控端脚本 # ansible t ...

  2. [HDU1403]Longest Common Substring(后缀数组)

    传送门 求两个串的公共子串(注意,这个公共子串是连续的一段) 把两个串连在一起,中间再加上一个原字符串中不存在的字符,避免过度匹配. 求一遍height,再从height中找满足条件的最大值即可. 为 ...

  3. python在Linux中安装虚拟环境,区别python2和python3,分别安装模块

    安装虚拟环境的时候遇到的问题,解决的过程很闹心,在这里简单直接的分享出来,就是为了解决问题.  安装虚拟环境(须在联网状态下) $ sudo pip install virtualenv $ sudo ...

  4. Sencha Toucha 2.1 文件上传

    javascript代码: Ext.onReady(function() { Ext.create('Ext.form.Panel', { title: 'Upload a Photo', width ...

  5. Nginx不转发http header

    使用nginx做http代理时,在Header中使用了一个名为api_key的属性,碰到http header不转发的问题. 问题源码: rc = ngx_http_parse_header_line ...

  6. windows下swoole安装教程

    1)下载安装cygwin(根据操作系统选择32位或者64位): https://cygwin.com/install.html 选择在windows中虚拟环境的root目录 选择下载安装的网络节点,如 ...

  7. [bzoj1704][Usaco2007 Mar]Face The Right Way 自动转身机_贪心

    Face The Right Way 自动转身机 bzoj-1704 Usaco-2007 Mar 题目大意:不想描述题意系列++... ...题目链接 注释:略. 想法:我们直接枚举k,然后从左往右 ...

  8. N天学习一个linux命令之xargs

    用途 标准输入流读取参数(空格或者换行符分隔),传递给需要执行的命令 用法 xargs [options] [command [initial-arguments]] 常用选项 --arg-file= ...

  9. 一键解决ScrollView嵌套ListView仅仅显示一行的问题

    /** * 解决ScrollView嵌套ListView仅仅显示一行的问题 * * @param listView */ private void setListViewHeightBasedOnCh ...

  10. [Node.js] Add Logging to a Node.js Application using Winston

    Winston is a popular logging library for NodeJS which allows you to customise the output, as well as ...