05-- 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
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 ...
随机推荐
- JSON中getInt()和optInt()的区别
最近在用org.json这个包解析json的时候,发现谷歌提供两种不同的数据类型获取方法,比如说针对Int类型,提供了getInt()和optInt()两种方式,谷歌文档中的说明如下: 那么这两者有什 ...
- Drop all tables in MySQL database
Drop all tables in MySQL database Answer: MySQL does not have a command for removing all database ta ...
- Linux下diff与patch命令的配合使用
在Linux下,diff与patch命令配合使用可以进行简单的代码维护工作. [A] diff diff命令用于比较文件的差异,可以用于制作patch文件.但此命令参数众多.格式多样,所以在此仅介绍较 ...
- [bzoj3378][Usaco2004 Open]MooFest 狂欢节_树状数组
MooFest 狂欢节 bzoj-3378 Usaco-2004 Open 题目大意:给定一个n个数的a序列,每两个数之间有一个距离,两个点之间的权值为$max(a[i],a[j])*dis(i,j) ...
- Spring MVC-表单(Form)标签-文件上传(File Upload)示例(转载实践)
以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_upload.htm 说明:示例基于Spring MVC 4.1.6. 以下示例显 ...
- erlang Unicode 处理
最近在使用erlang做游戏服务器,而字符串在服务器编程中的地位是十分重要的,于是便想仔细研究下字符编码,以及erlang下的字符串处理.先从Unicode开始吧.... [Unicode] Unic ...
- Android开发之怎样监听让Service不被杀死
一.Service简单介绍 Service是在一段不定的时间执行在后台,不和用户交互应用组件. 每一个Service必须在manifest中 通过<service>来声明. 能够通过con ...
- KD树——k=1时就是BST,里面的数学原理还是有不明白的地方,为啥方差划分?
Kd-Tree,即K-dimensional tree,是一棵二叉树,树中存储的是一些K维数据.在一个K维数据集合上构建一棵Kd-Tree代表了对该K维数据集合构成的K维空间的一个划分,即树中的每个结 ...
- bzoj1116 [POI2008]CLO——并查集找环
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1116 分析性质,只要有环,那么给环定一下向就满足了条件: 环上点的其他边可以指向外面,所以两 ...
- Python27天 反射 ,isinstance与ssubclass 内置方法
所学内容 反射 1.hasattr ( 判断一个属性在对象里有没有 ) -------------------- [对象,字符串属性]本质是:# 判断 ' name ' in obj.__dict__ ...