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++ 静态成员变量的更多相关文章
- spring注入静态成员变量提示invalid setter method
果然还是不够细心啊,被坑一晚上.. 一个极其简单的小程序,但是需要通过xml文件配置注入一个值,唯一的特别是要注入的属性是类中的静态成员变量.. 如下,然后自动生成get和set方法..坑就从此开始了 ...
- C#泛型-小心使用静态成员变量
对于泛型类的声明 其中使用类型参数的构造类型,比如List<T>被称为开放构造类型(open constructed type)而不使用类型参数的构造类型,例如List<int> ...
- C++@类的静态成员变量和静态成员函数
参考: http://blog.csdn.net/morewindows/article/details/6721430 http://www.cnblogs.com/lzjsky/archive/2 ...
- C++学习10 static静态成员变量和静态成员函数
一般情况下,如果有N个同类的对象,那么每一个对象都分别有自己的成员变量,不同对象的成员变量各自有值,互不相干.但是有时我们希望有某一个或几个成员变量为所有对象共有,这样可以实现数据共享. 可以使用全局 ...
- 静态成员变量.xml
pre{ line-height:1; color:#1e1e1e; background-color:#f0f0f0; font-size:16px;}.sysFunc{color:#627cf6; ...
- java:静态成员变量和静态函数
静态成员变量 可以使用类名调用,如 class Dog { static int age; } class Test2{ public static void main(String args[]){ ...
- C++类中的静态成员变量与静态成员函数的使用
代码: #include <iostream> #include <string> #include <cstdio> using namespace std; c ...
- C++类中的静态成员变量与静态成员函数
最近一直看c++相关的项目,但总是会被c++类中的静态成员变量与静态成员函数的理解感觉很是模糊,不明白为什么类中要是用静态成员变量.于是在网上搜集了一些资料,自己再稍微总结下. 静态成员的概念: 静态 ...
- C# 父子类_实例_静态成员变量_构造函数的执行顺序
今天去面试的时候被一道题问得一点脾气都没有,今天特地来研究下. 子类成员变量,子类静态成员变量,子类构造函数,父类成员变量,父类静态成员变量,父类构造函数的执行顺序. 现在贴上从另外一个.net程序员 ...
- C++静态成员函数不能调用非静态成员变量
其实我们从直观上可以很好的理解静态成员函数不能调用非静态成员变量这句话因为无论是静态成员函数还是静态成员变量,它们 都是在类的范畴之类的,及在类的整个生存周期里始终只能存在一份.然而非静态成员变量和非 ...
随机推荐
- Android Gradle 引用本地 AAR 的几种方式
折衷方案: 1.方式2 - 不完美解决办法2 2.再使用"自定义Gradle代码"来减轻重复设置的问题. 自定义Gradle代码如下: repositories { flatDir ...
- 修改ultisnips的默认键
把ultisnips修改和textmate一致. <tab>展开代码,再按<tab>跳转到下一个占位符,<shift+tab>跳转上一个占位符. 在vim配置文件中 ...
- 强者联盟——Python语言结合Spark框架
引言:Spark由AMPLab实验室开发,其本质是基于内存的高速迭代框架,"迭代"是机器学习最大的特点,因此很适合做机器学习. 得益于在数据科学中强大的表现,Python语言的粉丝 ...
- gitlab yum 源
https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/
- 每日英语:Our Unique Obsession With Rover And Fluffy
Recently, an almost literal case of lifeboat ethics occurred. On Aug. 4, Graham and Sheryl Anley, wh ...
- ny168 房间安排
房间安排 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 2010年上海世界博览会(Expo2010),是第41届世界博览会.于2010年5月1日至10月31日期间,在中 ...
- Oracle PLSQL Demo - 20.弱类型REF游标[没有指定查询类型,也不指定返回类型]
declare Type ref_cur_variable IS REF cursor; cur_variable ref_cur_variable; v_ename ); v_deptno ); v ...
- Hbase shell 常用命令(1)
下面我们看看HBase Shell的一些基本操作命令,我列出了几个常用的HBase Shell命令,如下: 名称 命令表达式 创建表 create '表名称', '列名称1','列名称2','列名称N ...
- python 高阶函数 map lambda filter等
map 描述 map() 会根据提供的函数对指定序列做映射. 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表. ...
- 【Unity笔记】碰撞器(Collision)与触发器(Trigger)的区别
当碰撞器Collision组件身上的属性IsTrigger勾选为True时,该碰撞器就成了触发器. 区别:1.能够产生的回调和函数不同.碰撞器:MonoBehaviour.OnCollisionEnt ...