说到构造函数,通常是将讲对象创建时编译器自动调用构造函数为对象初始化,也可以说是分配内存空间。
学习了构造函数 相对其中牵涉到的一些点作下大概的了解和学习,整理一下只是点。
这里主要说下 类与结构体的差异/类与结构体包含继承关系时的构造调用/类的初始化列表/默认构造函数/拷贝构造函数以及牵涉到的相关内容
结构体和类的区别
对于结构中的实例字段成员,不能在声明时赋值初始化
声明了结构类型后,可以使用new运算符创建构造对象,也可以不用new。若不用new,那在初始化所有字段之前,字段将保持未赋值状态且对象不可用
结构在堆栈中创建,是值类型,而类是引用类型
值类型和引用类型的区别
byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。值类型变量声明后,不管是否已经赋值,编译器为其分配内存
string 和 class统称为引用类型。当声明一个类时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间。当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中
注:new 的位置可以堆可以栈?如何查看具体的位置呢? --- linux
最后一项是映射的文件名。对匿名映射来说,是此段虚拟内存在进程中的角色。[stack]表示在进程中作为栈使用,[heap]表示堆。其余情况则无显示
第一个示例可以确认的是new的数据此时并不在堆数据区中/ then……实际上应该在哪呢?——待确认【==|`】
结构体与类的构造函数--包含&继承 关系下是否会有差异呢?
他们之间的调用初始化关系: 初始化会分配空间和赋随机值
示例:-(S=Struct C=Class Con=Conntain Inher=Inherit)
结论:不论包含还是继承 都会调用 相关的构造函数,不用多次给成员初始化处理
此处需要使用单步调试确认顺序 (VS2017 使用F10调试)
-
包含关系中,按照成员声明的顺序进行构造初始化,而不是按照初始化列表的顺序初始化
-
-
继承关系中,先调用父类的构造 ,再按照声明的顺序
初始化列表 & 默认构造函数 & 静态构造函数 & 拷贝构造函数
需使用初始化列表的条件:
数据成员是对象,并且这个对象只有含参数的构造函数,没有无参数的构造函数
对象引用或者cosnt修饰的数据成员
子类初始化父类的私有成员,需要在(并且也只能在)参数初始化列表中显示调用父类的构造函数
默认构造函数:
-
没有带明显形参的构造函数。
-
提供了默认实参的构造函数。
warning: 编译器自动合成默认构造函数的误区
合成默认构造函数总是不会初始化类的内置类型及复合类型的数据成员。(如 int / bool ……)
分清楚默认构造函数被程序需要与被编译器需要,只有被编译器需要的默认构造函数,编译器才会合成它
编译器需要去合成默认构造的条件:
含有类对象数据成员,该类对象类型有默认构造函数
基类带有默认构造函数的派生类
带有虚函数的类
带有虚基类的类
静态构造函数
1.静态构造函数既没有访问修饰符,也没有参数
2.在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类
3.无法直接调用静态构造函数
4.在程序中,用户无法控制何时执行静态构造函数
拷贝构造函数
一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。
作用就是用来复制对象的,在使用这个对象的实例来初始化这个对象的一个新的实例