第一部分 ---- 初始化列表
?
传统方式初始化显得比较麻烦,于是c++给我们提供了初始化列表的语法来初始化属性:
构造函数(可有参数也可无参数):属性1(值1) ,属性2(值2)....{ 花括号内放的依然是函数的实现 }
如果在写值的括号内写常量10,15啥的话,那么无论是那个对象赋予其属性的初始值都是定死的,那么怎样才能在适用初始化列表的同时保持每个对象的定制初始化呢?
答案就是上图这样:
写值的括号里可以写变量,然后函数的小括号里依然可以创建形参变量
通过创建形参变量,然后在写值的括号里写形参变量,然后传值给形参变量就能够实现定制初始化
第二部分 --- 类对象作为类成员

即一个类B的成员可以是一个对象,且这个对象的类是和B不同的类A
我们称这个对象a为B的对象成员?
这样子初始化对象m_Phone是可以的? --- 因为上面的构造函数m_Phone那部分就相当于:
Phone m_Phone = pName ---> 这个就是我们之前学的调用构造函数的一种方法 --- 隐式转换法,通过隐式转换法编译器就能够成功调用构造函数来给对象m_Phone中的属性初始化了,当m_Phone的所有成员属性都被初始化后,m_Phone这个对象就初始化完毕了。
如果想要访问对象成员的成员属性的话就需要用到多个点操作符了。
当前对象 . 对象成员 . 对象成员的成员属性?
补充部分:?
?在上面这张图中,第一个函数是Person的构造函数而m_Phone则是Person的对象成员。
当我们在创建类为Person的对象的时候,第一步会先走到类中的构造函数处,不过这里很特别的是我们用的是列表初始化语法!!所以在执行Person的构造函数之前我们要先执行列表初始化语法 ---- 而列表初始化语法的执行逻辑是:
属性类型 属性名 = 括号赋予属性的初始值
如 string m_Name = name
当成员属性是对象的时候,就出现这样一行代码:
Phone m_Phone = pName --- 这是一个隐式转换调用构造函数,所以我们要先调用对象成员m_Phone的构造函数,当一切都赋值完后我们才开始调用Person中的构造函数
综上:
1.当构造函数处有列表初始化语法时,先要执行列表初始化
2.列表初始化的执行逻辑是:成员属性的类型 成员属性名 = 括号内要赋给成员属性的值
如 int a = 10
3.如果一个类中有对象成员的话,那么这个类的成员初始化最好选择列表初始化法,因为这样子可以符合先调用对象成员的构造函数,在调用本类的构造函数的语法要求
析构函数的调用顺序则是反过来。
第三部分 --- 静态成员

?第一小节 --- 静态成员变量
1.在编译阶段分配内存(即在程序生成之前就已经分配好内存了),程序生成前能够分配内存的内存区有全局区和代码区,而静态变量都在全局区中分配内存
2.静态成员变量必须在类内声明,类外定义 ---?注意把类外初始化改为类外定义
3.用static修饰的成员变量就是静态成员变量
上面这张图显示的就是静态成员变量的类内声明和类外定义?
类内声明就没什么好说的,最重要的是类外定义
如果我们没有进行类外初始化的话,会出现的结果就是我们在通过对象加点操作符的方式去访问这个静态成员变量时会访问失败,并导致程序出错
出错的原因是:静态成员变量在类中只是进行了变量声明,而变量声明是不会给变量分配内存的,所以我们需要在类外为静态成员变量进行变量定义,使其获得内存来存储数据,这样子我们才能够正常的访问静态成员变量
静态成员变量的定义的语法如下:
静态成员变量的类型 静态成员变量所在的类的类名 ::(两个冒号) 静态成员变量名( = 一个数值,这个可写可不写,写了的话就相当于给静态成员变量初始化了一个值) ;
将上面这一行代码写在所有函数之外,即让静态成员变量成为全局变量
完成了上面的步骤之后我们就成功的为静态成员变量实现了变量定义,使其拥有了内存空间供我们访问和操作。
静态成员变脸量还可以通过类名来访问,访问的语法是:
静态成员变量所属的类的类名 ::(两个冒号) 静态成员变量名?
成员变量则只能通过对象名来访问
(ps:静态成员变量也是有访问权限的)
第二小节 --- 静态成员函数

?
在函数的返回类型的左边加上?static 修饰函数,就能让函数变为静态函数
静态成员函数的调用方法和静态成员变量一样都有两种 --- 通过对象名 / 通过类名?? 静态成员函数内部只能够访问静态成员变量,不可以访问普通的成员变量
首先静态成员是大家共有的函数,所以它不会因为所属的对象不同而不同,即对象A的静态成员函数和对象B的静态成员函数是同一个(A和B同类),但是普通的成员函数则会因为所属的对象不同而不同,比如 对象A的成员函数fun() 就和对象B的成员函数fun()不同
因为创建一个对象就相当于将类的内容拷贝了一份然后分配个这个对象,拷贝的内容所占据的内存空间都是属于这个对象的 ---?每一个对象(同一类)虽然拷贝的内容一样,但是它们所占据的内存空间不同,所以在计算机看来它们就是不同的 ---?而静态成员变量/函数则是每一个对象共有的一块内存空间,所以每一个对象的静态部分都是一样的
然后在静态成员函数这一个每一个对象都可以来的公共区域说你要私有私有物品是允许的,但是由于这是公共空间而不是你家(在你家的话会自动识别是用你的私有物品),且你所拥有的私有物品每一个人都有,所以只说使用私有物品是不行的,因为计算机无法判断你要使用使用谁的私有物品,你必须在这个“私有物品”前加上对象名和点操作符告诉计算机是谁的私有物品才行!
而公共设施则是共有的,使用时无需声明是谁的!
如下图:
所以在我们调用静态成员函数/变量的时候调用的是每一个对象共有的一块内存空间
(静态成员函数也是有访问权限的)
(在类中只能够不加对象名直接访问成员变量,且此时的成员变量在类这个局部区域中就相当于全局变量)
第四部分 --- 成员变量和成员函数分开存储
1.创建一个对象就相当于对类进行了一次拷贝并存放在一个新开辟的内存空间中
2.被拷贝的类中有非静态成员变量/函数与静态成员变量/函数
3.其中非静态成员变量会随着类的拷贝也会被拷贝一份,拷贝后的副本就是独属于来拷贝的对象的,被存在创建对象的时候所开辟的内存空间中(非静态成员函数也只有一份,它不会随着对象的创建而多拷贝一份)
4.静态成员变量/函数则是在任何对象创建之前就已经被分配好内存空间储存好了,每一个对象都能够访问它,它是属于所有对象的公共空间 --- 由于是公共空间,所以这个空间只有一个,并不需要给每一个对象都拷贝一份。

问题:创建一个对象的时候,这个对象究竟占据多少的内存空间??
求解方法:用sizeof关键字来就对象对应的类型 --- 类 所开辟的内存空间的大小?
(对象与类的关系和变量与类型的关系是一样的 --- 当我们创建变量的时候要为变量开辟内存空间,那么问题来了 --- 计算机根据什么来开辟内存空间呢?答案就是根据变量的类型。变量的类型相当于是一份蓝图,这份蓝图本身不占内存空间,但是蓝图中包含了变量所需的内存空间大小和内存空间的类型 --- sizeof关键字就是通过查蓝图的方式来获取变量的内存空间大小 --- 单位是字节
对象和类也是同理)
首先我们需要明确一个事实:
1.每一个对象都应该具有独一无二的内存空间
开始推理:
如果空类的内存空间规划为0,那么我们在通过空类创建空对象的时候就违背了上面哪一个事实(内存空间规划为0 --- 不分配内存空间? ---- 违背事实)
如果1.不是空类?2.类中只有非静态成员变量的话 --- 则类的内存空间规划就等于类中的成员变量内存空间总和
1.类中的静态成员变量不占类的内存空间规划,它的内存空间是我们通过类外定义获得的,而不是通过类的内存空间规划获得的。
2.非静态成员函数和静态成员函数的内存空间都只有一份,且它们都不占类的内存空间规划
?
|