C++ 类的静态成员详细讲解
在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。
静态成员的定义或声明要加个关键static。静态成员可以通过双冒号来使用即<类名>::<静态成员名>。
在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象。希望阅读本文可以使读者对类的静态成员变量和成员函数有更为深刻的认识。
第一个例子,通过类名调用静态成员函数和非静态成员函数
- class Point
- {
- public:
- void init()
- {
- }
- static void output()
- {
- }
- };
- void main()
- {
- Point::init();
- Point::output();
- }
编译出错:error C2352: 'Point::init' : illegal call of non-static member function
结论1:不能通过类名来调用类的非静态成员函数。
第二个例子,通过类的对象调用静态成员函数和非静态成员函数
将上例的main()改为:
- void main()
- {
- Point pt;
- pt.init();
- pt.output();
- }
编译通过。
结论2:类的对象可以使用静态成员函数和非静态成员函数。
第三个例子,在类的静态成员函数中使用类的非静态成员
- #include <stdio.h>
- class Point
- {
- public:
- void init()
- {
- }
- static void output()
- {
- printf("%d\n", m_x);
- }
- private:
- int m_x;
- };
- void main()
- {
- Point pt;
- pt.output();
- }
编译出错:error C2597: illegal reference to data member 'Point::m_x' in a static member function
因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以这个调用就出错了,就好比没有声明一个变量却提前使用它一样。
结论3:静态成员函数中不能引用非静态成员。
第四个例子,在类的非静态成员函数中使用类的静态成员
- class Point
- {
- public:
- void init()
- {
- output();
- }
- static void output()
- {
- }
- };
- void main()
- {
- Point pt;
- pt.output();
- }
编译通过。
结论4:类的非静态成员函数可以调用用静态成员函数,但反之不能。
第五个例子,使用类的静态成员变量
- #include <stdio.h>
- class Point
- {
- public:
- Point()
- {
- m_nPointCount++;
- }
- ~Point()
- {
- m_nPointCount--;
- }
- static void output()
- {
- printf("%d\n", m_nPointCount);
- }
- private:
- static int m_nPointCount;
- };
- void main()
- {
- Point pt;
- pt.output();
- }
按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时出错。
再给一个利用类的静态成员变量和函数的例子以加深理解,这个例子建立一个学生类,每个学生类的对象将组成一个双向链表,用一个静态成员变量记录这个双向链表的表头,一个静态成员函数输出这个双向链表。
- #include <stdio.h>
- #include <string.h>
- const int MAX_NAME_SIZE = 30;
- class Student
- {
- public:
- Student(char *pszName);
- ~Student();
- public:
- static void PrintfAllStudents();
- private:
- char m_name[MAX_NAME_SIZE];
- Student *next;
- Student *prev;
- static Student *m_head;
- };
- Student::Student(char *pszName)
- {
- strcpy(this->m_name, pszName);
- //建立双向链表,新数据从链表头部插入。
- this->next = m_head;
- this->prev = NULL;
- if (m_head != NULL)
- m_head->prev = this;
- m_head = this;
- }
- Student::~Student ()//析构过程就是节点的脱离过程
- {
- if (this == m_head) //该节点就是头节点。
- {
- m_head = this->next;
- }
- else
- {
- this->prev->next = this->next;
- this->next->prev = this->prev;
- }
- }
- void Student::PrintfAllStudents()
- {
- for (Student *p = m_head; p != NULL; p = p->next)
- printf("%s\n", p->m_name);
- }
- Student* Student::m_head = NULL;
- void main()
- {
- Student studentA("AAA");
- Student studentB("BBB");
- Student studentC("CCC");
- Student studentD("DDD");
- Student student("MoreWindows");
- Student::PrintfAllStudents();
- }
程序将输出:

当然在本例还可以增加个静态成员变量来表示链表中学生个数,如果读者有兴趣,就将这个作为小练习吧。
原文地址:http://blog.csdn.net/morewindows/article/details/6721430
C++ 类的静态成员详细讲解的更多相关文章
- 05-- C++ 类的静态成员详细讲解
C++ 类的静态成员详细讲解 在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不 ...
- 面向对象课后深入学习(C++ 类的静态成员详细讲解)
今天在刚申请了博客,一下午都在写那个随笔,所以说好的来看c++的也放在了最后,下星期就考试了,这个类的静态成员是我不是很懂的,在网上 看到一片很详细的博客考下来回去慢慢看. 在C++中,静态成员是属于 ...
- C++ 类的静态成员详细讲解(转)
在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...
- C++ 类的静态成员详细讲解[转]
在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...
- 转:C++ 类的静态成员详细讲解
在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节 ...
- 简单Java类 全网最详细讲解 !!!
最近学习java非常吃力,学习的进度很快,由于基础没打牢固,整体上项目理解很吃力,偶尔会遇到一些基本的概念,都会阻碍整体的理解.最近也看了不少的视频讲解,听得很迷,最后搞得很乱,没有明确的学习目标,今 ...
- 【Cocos2d-X开发学习笔记】第12期:动作类CCAction的详细讲解
一般对于游戏中的精灵而言,它们不仅仅是存在于场景中,而且是动态展现的,例如,精灵移动的动态效果.动 画效果.跳动效果.闪烁和旋转动态效果等.每一种效果都可以看成是精灵的一个动作. 一.动作类(CCAc ...
- [VC++]用CTime类得到当前日期、时间、星期,格式化(详细讲解)
用CTime类得到当前日期.时间.星期,格式化(详细讲解)2009/05/12 09:48 A.M.① 定义一个CTime类对象 CTime time; ② 得到当前时间 time = CTime:: ...
- 第四节:详细讲解Java中的类和面向对象思想
前言 大家好,给大家带来详细讲解Java中的类和面向对象思想的概述,希望你们喜欢 类和面向对象 在Java中怎样理解对象,创建对象和引用:什么是引用,对于基础学习的同学,要深入了解引用.示例:Stri ...
随机推荐
- C# 将DataTable存储到DBF文件中
(准备)生成一个DataTable /// <summary> /// 生成一个数据表 /// </summary> /// <returns></retur ...
- tcp协议-http协议-time-wait-close-wait必知
前言: tcp四次挥手过程中,谁主动断开,谁有time_wait,被动断开一方会有close_wait time_wait:保持端口占用2mls~4min,避免对方还有一些tcp片发往这个端口,新 ...
- vi的查找与替换
0x01 查找 (在命令行模式下) /<要查找的字符> 向下查找要查找的字符 ?<要查找的字符> 向上查找要查找的字符 0x02 替换 (在底行模式下) :0,$s/s ...
- NHibernate系列文章十二:Load/Get方法
摘要 NHibernate提供两个方法按主键值查找对象:Load/Get. 1. Load/Get方法的区别 Load: Load方法可以对查询进行优化. Load方法实际得到一proxy对象,并不立 ...
- glReadPixels函数
GPU渲染完数据在显存,回传内存的唯一方式glReadPixels函数... glReadPixels:读取一些像素.当前可以简单理解为“把已经绘制好的像素(它可能已经被保存到显卡的显存中)读取到内存 ...
- Python自动化 【第十篇】:Python进阶-多进程/协程/事件驱动与Select\Poll\Epoll异步IO
本节内容: 多进程 协程 事件驱动与Select\Poll\Epoll异步IO 1. 多进程 启动多个进程 进程中启进程 父进程与子进程 进程间通信 不同进程间内存是不共享的,要想实现两个进程间 ...
- regression build test
Q: 什么是regression test以及为什么做regression test? A: fixing1进到build之后,QA/tester要进行手动测试,也可能会写automation.但是随 ...
- cursor
BeginWaitCursor(); // display the hourglass cursor // do some lengthy processing Sleep(3000); EndWai ...
- Spark Streaming
Spark Streaming Spark Streaming 是Spark为了用户实现流式计算的模型. 数据源包括Kafka,Flume,HDFS等. DStream 离散化流(discretize ...
- -Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable
在 myEclipse 中 需要配置 解决方法: window --> preferences --> java --> installed JREs 设置 Default VM A ...