C++ 类的静态成员详细讲解-阿里云开发者社区

开发者社区> 范大脚脚> 正文

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

简介:
+关注继续查看

http://blog.csdn.net/morewindows/article/details/6721430

 

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

静态成员的定义或声明要加个关键static。静态成员可以通过双冒号来使用即<类名>::<静态成员名>。

 

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象。希望阅读本文可以使读者对类的静态成员变量和成员函数有更为深刻的认识。

 

第一个例子,通过类名调用静态成员函数和非静态成员函数

[cpp] view plaincopy
 
  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()改为:

[cpp] view plaincopy
 
  1. void main()  
  2. {  
  3.     Point pt;  
  4.     pt.init();  
  5.     pt.output();  
  6. }  

编译通过。

结论2:类的对象可以使用静态成员函数和非静态成员函数。

 

第三个例子,在类的静态成员函数中使用类的非静态成员

[cpp] view plaincopy
 
  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:静态成员函数中不能引用非静态成员。

 

第四个例子,在类的非静态成员函数中使用类的静态成员

[cpp] view plaincopy
 
  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:类的非静态成员函数可以调用用静态成员函数,但反之不能。

 

第五个例子,使用类的静态成员变量

[cpp] view plaincopy
 
  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时出错。

 

再给一个利用类的静态成员变量和函数的例子以加深理解,这个例子建立一个学生类,每个学生类的对象将组成一个双向链表,用一个静态成员变量记录这个双向链表的表头,一个静态成员函数输出这个双向链表。

[cpp] view plaincopy
 
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. const int MAX_NAME_SIZE = 30;    
  4.   
  5. class Student    
  6. {    
  7. public:    
  8.     Student(char *pszName);  
  9.     ~Student();  
  10. public:  
  11.     static void PrintfAllStudents();  
  12. private:    
  13.     char    m_name[MAX_NAME_SIZE];    
  14.     Student *next;  
  15.     Student *prev;  
  16.     static Student *m_head;  
  17. };    
  18.   
  19. Student::Student(char *pszName)  
  20. {    
  21.     strcpy(this->m_name, pszName);  
  22.   
  23.     //建立双向链表,新数据从链表头部插入。  
  24.     this->next = m_head;  
  25.     this->prev = NULL;  
  26.     if (m_head != NULL)  
  27.         m_head->prev = this;  
  28.     m_head = this;    
  29. }    
  30.   
  31. Student::~Student ()//析构过程就是节点的脱离过程    
  32. {    
  33.     if (this == m_head) //该节点就是头节点。  
  34.     {  
  35.         m_head = this->next;  
  36.     }  
  37.     else  
  38.     {  
  39.         this->prev->next = this->next;  
  40.         this->next->prev = this->prev;  
  41.     }  
  42. }    
  43.   
  44. void Student::PrintfAllStudents()  
  45. {  
  46.     for (Student *p = m_head; p != NULL; p = p->next)  
  47.         printf("%s\n", p->m_name);  
  48. }  
  49.   
  50. Student* Student::m_head = NULL;    
  51.   
  52. void main()    
  53. {     
  54.     Student studentA("AAA");  
  55.     Student studentB("BBB");  
  56.     Student studentC("CCC");  
  57.     Student studentD("DDD");  
  58.     Student student("MoreWindows");  
  59.     Student::PrintfAllStudents();  
  60. }  

程序将输出:

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

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

 


本文转自wanqi博客园博客,原文链接:http://www.cnblogs.com/wanqieddy/p/4369361.html,如需转载请自行联系原作者




版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
C++多态简析——静态多态与动态多态
C++多态简析——静态多态与动态多态
1784 0
关于初始化C++类成员
在使用C++编程的过程当中,常常需要对类成员进行初始化,通常的方法有两种: 第一种方法: CMYClass::CSomeClass() { x=0; y=1; } 第二种方法: CSomeClass::CSomeClass() : x(0), y(1) { } 本文将要探讨这两种方法的异同以及如何使用这两种方法。
725 0
JSP-讲解(生成java类、静态导入与动态导入)
一、JSP技术简介 JSP是Java Server Page的缩写,它是Servlet的扩展,它的作用是简化网站的创建和维护。 JSP是HTML代码与Java代码的混合体。 JSP文件通常以JSP或JSPX的扩展名。
1133 0
JAVA中的静态成员
//Java中的静态成员 /* *静态的成员变量是属于类的,不属于某个对象,是共享的。 * 访问时可以用类名.静态属性直接访问,也可以用对象.访问,后者不提倡。 * 静态的成员方法只能访问静态的成员 */ class Point{ static int age ; //所有人共用a...
636 0
普通(非模板)类的成员模板
16.21 编写你自己的DebugDelete版本。 #include #include using namespace std; class DebugDelete { public: DebugDelete(ostream &s=cerr):os(s) {} ...
526 0
+关注
3656
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载