面向对象课后深入学习(C++ 类的静态成员详细讲解)

今天在刚申请了博客,一下午都在写那个随笔,所以说好的来看c++的也放在了最后,下星期就考试了,这个类的静态成员是我不是很懂的,在网上 看到一片很详细的博客考下来回去慢慢看。

在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" ([email protected]@@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
 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

仔细看过以后感觉楼主写的非常好,对我有很多启发。哈哈
除此之外 ,我感觉还有个小瑕疵,就是析构函数还可以再严谨些。

 1 Student::~Student ()//析构过程就是节点的脱离过程
 2 {
 3     if (this == m_head) //该节点就是头节点。
 4     {
 5         Student *ptmp = m_head;
 6         m_head = this->next;
 7         cout << "in destructor head " << endl;
 8     }
 9                 else if(this->next == NULL)
10                 { this->pre->next =NULL ;}
11                 else {
12         this->prev->next = this->next;
13         this->next->prev = this->prev;
14     }
15 }   

我增加了 
else if(this->next == NULL) 
{ this->pre->next =NULL ;}
否则 this->next->prev 将有问题,因为 this->next 都NULL了 还怎么能找prev域呢? 
测试: new *p1 = ...
new *p2 = ...
new *p3 = ...
//单独 delete p3 is fine
//单独 delete p2 is fine
单独 but delete p1 is wrong //这是最后一个,因为是前插
修改后的析构函数没有这类问题了。均能正常调用析构函数析构。

2016-06-21

20:13:22

时间: 2024-11-04 13:47:26

面向对象课后深入学习(C++ 类的静态成员详细讲解)的相关文章

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

在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存. 静态成员的定义或声明要加个关键static.静态成员可以是Public,Private,Protected:Public的静态成员可以通过双冒号来使用即<类名>::<静态成员名>. 在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变

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

在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存. 静态成员的定义或声明要加个关键static.静态成员可以通过双冒号来使用即<类名>::<静态成员名>. 在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象.希望阅读本文可以使读者对类的静

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

在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存. 静态成员的定义或声明要加个关键static.静态成员可以通过双冒号来使用即<类名>::<静态成员名>. 在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象.希望阅读本文可以使读者对类的静

C# 学习之 类的静态成员

我们可以使用 static 关键字把类成员定义为静态的.当我们声明一个类成员为静态时,意味着无论有多少个类的对象被创建,只会有一个该静态成员的副本. 关键字 static 意味着类中只有一个该成员的实例. 静态变量用于定义常量,因为它们的值可以通过直接调用类而不需要创建类的实例来获取. 静态变量可在成员函数或类的定义外部进行初始化.你也可以在类的定义内部初始化静态变量. ---------------------------------------------------------------

分布式缓存技术redis学习系列(二)——详细讲解redis数据结构(内存模型)以及常用命令

Redis数据类型 与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多,常用的数据类型主要有五种:String.List.Hash.Set和Sorted Set. Redis数据类型内存结构分析 Redis内部使用一个redisObject对象来表示所有的key和value.redisObject主要的信息包括数据类型(type).编码方式(encoding).数据指针(ptr).虚拟内存(vm)等.type代表一个value对象具体是何种数

简单Java类 全网最详细讲解 !!!

最近学习java非常吃力,学习的进度很快,由于基础没打牢固,整体上项目理解很吃力,偶尔会遇到一些基本的概念,都会阻碍整体的理解.最近也看了不少的视频讲解,听得很迷,最后搞得很乱,没有明确的学习目标,今天翻了翻书本,看到里面讲的很细,然后恍然大悟.话不多说,自己再整体的梳理一遍. 首先,下面列出关键词:类  属性  方法  对象  实例化对象  构造方法  初始化  局部变量  成员变量    之前每次遇到这些关键词,头都大了. 接下来我一点一点的讲: 1.什么是类: 定义:表示一个客观世界中某类

C++面向对象学习-类的静态成员

1 静态数据成员 2 1,sizeof 运算符不会计算静态成员. 3 4 2,对静态成员数据初始化的顺序为它们在类体外声明的顺序. 5 6 3,静态数据成员被类的所有对象所共享,包括该类的派生类对象. 7 8 4,静态成员数据也可以分为公有的.私有的和受保护的静态成员. 9 对公有静态成员,即可以通过类的对象进行访问,也可以通过类名直接访问. 10 私有的和保护的静态成员数据则只能被该类的公有成员函数访问. 11 12 5,在创建任何对象之前,类的静态成员数据已经存在并可以引用. 13 14 6

面向对象学习【类-静态类】

静态类只能包含静态成员(使用该类创建的所有对象将共享这些成员的同一个副本).静态类纯粹作为工具方法和字段的一个容器来使用.静态类不能包含任何实例数据或方法.另外,使用new操作符来创建静态类的一个对象是没有意义的.如果坚持这样做,编译器会报错.如果需要执行任何初始化,那么static类可以包含一个默认的构造器,前提是该构造器也被声明为static.其他任何类型的构造器都是非法的,编译器会报错: 比如自己定义一个Math类,其中只包含静态成员,那么应该像下面这样写: public static c

面向对象学习【类-匿名类】

匿名类是就就像这个词一样,是一个没有名字的类,看到这个匿名类有点迷糊了,如果大家想想一个类没有名称的话那么我们如何来使用他创建实例呢?答案就是我们可以使用 var 来声明一个匿名的类,创建的格式为: new anonymousClassName{字段1,字段2,........} 说明: 匿名类当中的字段都全部都是public类型的,这就意味着我们可以在外部随意有访问这个所谓的匿名类: 看着这么爽其实这个匿名类还有很多的限制如: 1.使用匿名类时,必须对其初始化: 2.只能包含public字段;