面向对象-静态成员
静态成员、友元、常成员、对象成员
今天刚刚结束了C++的第五周课程,老师讲的非常的好,本人收获颇丰,故此记录,以备复习之用。本文主要的内容就是围绕着静态成员,友元,常成员和成员对象展开的。
类
每一讲课的知识点,老师都是用一个程序为例子来讲解的,所以开篇点题,先把需要用到的类拿出来使用
第一个是CMyDate
的类
1 | class CMyDate { |
第二个是CPlayer
的类
1 | class CPlayer { |
主程序与函数定义
1 | //静态数据成员定义与初始化 |
其实大部分的知识点都在注释里面了,但是需要剖丝抽茧的把他细细讲解一下,从而可以更加的清楚
静态成员
什么是静态成员:在C++中,我们用static
关键字来表示静态成员,例如在Cplayer
类中定义了static int nObjNum;
存储位置:与C语言相似,静态成员与类的对象不在同一个存储位置,而是当类中声明静态成员的时候,就会自动为该成员分配一块空间
静态成员存储在全局数据区
,这也是一个类不同的对象都共享
这一个变量的原因。
静态成员的变量不属于对象,而是属于类,所以他必须进行
类外定义
实际上,并不需要像程序中那样,专门的进行**int CPlayer::nObjNum = 0;**的初始化,不赋值则默认的初始化是0
(补充知识点)一个完整程序的内存分布如下
- 代码区:存放函数体的二进制代码,由操作系统进行管理的
- 全局数据区:存放静态数据(即使是函数内部的静态局部变量)和全局变量,全局数据区的数据
不会因为函数的退出而释放空间
- 栈区:存放程序内部定义的局部变量,由系统控制,随着程序的退出自动释放空间
- 堆区:存放函数内部
new
出来的动态数据
参考资料
常成员
什么是常成员:用const
来修饰的成员,我们称之为常成员。在该程序中我们用const int NameSize来构造了一个常成员的函数用来修饰姓名长度。需要注意的地方时,在构造函数的时候,对于常成员函数的初始化,必须要在对象构造
之前初始化,那什么时候是对象构造之前呢?我们知道,每个对象的初始化都是由析构函数来进行构造的,而且析构函数在函数体中, 将我们想要初始化的值,赋值给对象的private变量
,那么我们要求在对象构造之前初始化,实际上就是要求在还没有进入构造函数的函数体的时候就初始化,更简单的来说,就是在{}之前进行初始化。所以,对于常成员的初始化,我们可以采用如下的形式:
1 | CPlayer::CPlayer(int nId, const char* name):NameSize(11), birthday(2003, 06, 14) |
此外,不仅仅是在构造函数中要求常成员提前初始化,事实上,只要涉及到对象中常成员的变化,就必须使得常成员初始化。
说明,对于NameSize(11),就是带参构造,其中括号内11就是给NameSize赋值11的意思。
对象成员
什么是对象成员:还是先看程序,在本程序中,我们首先定义了一个CMyDate
的类,然后再CPlayer
这个类中定义了一个CMyDate birthday,那么这个成员我们就称之为对象成员。
对象成员的构造:和常成员一样,对象成员必须在对象构造之间带参构造,具体代码和常成员相同。
构造同时赋值
事实上,不仅仅是常成员和对象成员可以在函数构造的同时赋值,对于任何一个成员来说,都可以在函数构造的同时赋值,具体的例子在程序中也有所展示
1 | CMyDate(int nYear, int nMonth, int nDay) :nYear(nYear),nMonth(nMonth),nDay(nDay){} |
在CMyDate中构造函数就可以实现带参赋值,这里有一点需要注意的是
不可以使用例如this->nYear(nYear)在函数构造同时赋值
原因是:this指针就是指向对象的指针,但是当我们在函数体外边赋值的时候,对象还没有构造完成,此时this指针并没有相应的指向,所以this->nYear会报错!!
友元函数
最后一个是友元函数,其实友元函数并不是一个好的机制,它并不是类的成员函数,要求声明在类中,但是定义要在类的外部。
为什么称它为友元,因为它不是类的成员函数,但是却可以直接访问类的私有成员变量
关键字:friend
友元类
这部分是拓展内容,详情请见