免费视频网站大全云购网站开发

当前位置: 首页 > news >正文

免费视频网站大全,云购网站开发,做班级的活动的网站,HTML网站页面建设目录 对象的初始化和清理#xff1a; why? 如何进行初始化和清理呢#xff1f; 使用构造函数和析构函数​编辑 构造函数语法: 析构函数语法: 构造函数的分类#xff1a; 两种分类方式#xff1a; 三种调用方法#xff1a; 括号法#xff08;默认构造函数调用 why? 如何进行初始化和清理呢 使用构造函数和析构函数​编辑 构造函数语法: 析构函数语法: 构造函数的分类 两种分类方式 三种调用方法 括号法默认构造函数调用 显示法 隐式转换法 拷贝调用函数的调用时机 1.使用一个已经常见完毕的对象来初始化一个新对象 2.值传递的方式给函数参数传值。 3.以值方式返回局部对象 构造函数调用时机 深拷贝浅拷贝 有可能的错误 错误原因 解决方案 深拷贝和浅拷贝案例 初始化列表 基本初始化列表案例 灵活定义初始化的数字时的初始化列表案例 类对象作为类成员 静态成员 静态成员变量 静态成员变量访问案例 访问方式 静态成员函数 静态成员函数创建调用基本示例 why? 结语 本篇博客讲解c入门学习④有关对象的初始化以及清理的知识点 传送门 c入门学习①-CSDN博客 c入门学习②-CSDN博客 c入门学习③——封装-CSDN博客 对象的初始化和清理 why? 为了保证数据安全一个对象或者是变量没有初始化则后面的后果是未知的同样没有清理也是可能会造成一系列的安全问题。 如何进行初始化和清理呢 使用构造函数和析构函数 构造函数语法: 类名(){} 1.构造函数没有返回值也不写void 2.函数名称与类名相同 3.构造函数可以有参数因此可以发生重载 4.程序在调用对象时候会自动调用构造无须手动调用,而且只会调用一次 自己不写程序会自动帮你实现不过函数里面的代码是空的要是自己写程序运行你自己写的构造函数 析构函数语法: ~类名(){} 1.析构函数没有返回值也不写void 2.函数名称与类名相同,在名称前加上符号 3.析构函数不可以有参数因此不可以发生重载 4.程序在对象销毁前会自动调用析构无须手动调用,而且只会调用一次 自己不写程序会自动帮你实现不过函数里面的代码是空的要是自己写程序运行你自己写的析构函数 代码 #includeiostream #includestring using namespace std; class person{public://创造构造函数person() {cout 构造函数 endl;}~person() {cout 析构函数调用 endl;} }; void test1() {person a; }//局部变量在栈区上创建test执行完毕后释放对象会自动实现析构函数不过是空的 //当自己创建了一个那么就执行自己创建的析构函数int main() {test1();system(pause);return 0; } 构造函数的分类 两种分类方式 按照参数分类有参数和无参数默认情况下为无参 按照类型分类普通和拷贝 拷贝copy、复制 例如personconst person a){namea.name;};把其他的属性拷贝到这个上面 拷贝方式创建注意括号里写要copy的对象并加上const以引用的方式写入。 三种构造函数的具体表示 #includeiostream #includestring using namespace std; class person{public://创造构造函数person() {cout 默认构造函数 endl;}person(int age) {cout 有参构造函数 endl;Age age;}person(const person p) {cout 拷贝构造函数 endl;Age p.Age;}~person() {cout 析构函数调用 endl;}int Age; }; 引用c引用-CSDN博客 三种调用方法 括号法默认构造函数调用 person p1;调用无参构造函数也是默认构造函数调用 person p2(12);调用有参构造函数 person p3(p2);调用拷贝构造函数 注意事项调用默认构造函数的时候不要加因为编译器会认为这个是一个函数声明不会认为在创建对象 显示法 person p1;默认构造 person p2person(12);有参构造 person p3person(p2);拷贝构造 单独拿出来person(12),称为匿名对象当前执行结束后系统会立即回收掉匿名对象马上析构掉 不单独看这个匿名对象就有名字了左边的就是它的名字 注意不要利用拷贝构造函数初始化匿名对象。编译器会认为person(p3)person p3;认为这是一个对象声明 隐式转换法 person p410;相当于写了person p4person(10)有参构造 person p5p4;拷贝构造 括号法最简单这里推荐使用这个 拷贝调用函数的调用时机 1.使用一个已经常见完毕的对象来初始化一个新对象 #includeiostream using namespace std; class person{public://创造构造函数person() {cout 默认构造函数 endl;}person(int age) {Age age;cout 有参构造函数 endl;}person(const person a) {Age a.Age;cout 拷贝构造函数 endl;}~person() {cout 析构函数调用 endl;}int Age; }; void test1() {person a;//局部变量在栈区上创建test执行完毕后释放对象 } //使用一个已经创建完毕的对象来初始化一个新的对象 void test2() {person p(20);//调用有参构造函数person p1(p);//调用拷贝构造函数 }int main() {//test1();test2();system(pause);return 0; } 输出结果  2.值传递的方式给函数参数传值。 #define _CRT_SECURE_NO_WARNINGS #includeiostream #includestring using namespace std; class person{public://创造构造函数person() {cout 默认构造函数 endl;}person(int age) {Age age;cout 有参构造函数 endl;}person(const person a) {Age a.Age;cout 拷贝构造函数 endl;}~person() {cout 析构函数调用 endl;}int Age; }; //值传递的方式给函数参数传值 void test(person p) { } void test3() {person p;//调用默认构造函数test(p);//调用拷贝构造函数因为这里是以值传入相当于拷贝一个副本传进去}int main() {//test1();//test2();test3();return 0; } 3.以值方式返回局部对象 示例 #define _CRT_SECURE_NO_WARNINGS #includeiostream #includestring using namespace std; class person{public://创造构造函数person() {cout 默认构造函数 endl;}person(int age) {Age age;cout 有参构造函数 endl;}person(const person a) {Age a.Age;cout 拷贝构造函数 endl;}~person() {cout 析构函数调用 endl;}int Age; };//以值返回局部对象 person test0() {person p;//局部对象在完成函数之后会被自动释放掉但是现在以值方式返回则在返回的时候会自动给创建一个新的对象cout p地址 (int) p endl;return p;//返回的是p拷贝的一个新的对象 } void test4() {person atest0();//这里的函数a没有调用析构函数和构造函数cout a地址 (int)a endl; } int main() {//test1();//test2();//test3();test4();system(pause);return 0; } 构造函数调用时机 默认情况添加的函数 ⭐注意拷贝构造函数默认情况下只写值传递语句不会出现输出语句 构造函数调用规则如下: 若用户定义有参构造函数c不再提供默认无参构造但是会提供默认拷贝构造函数 当仅定义有参构造函数时不要进行默认无参构造会发生错误显示没有默认无参构造函数。 若用户定义拷贝构造函数c不会再次提供其他构造函数 只定义拷贝构造函数时如果使用其他的构造函数则会发生错误 深拷贝浅拷贝 一般浅拷贝是逐个字节依次复制过去而默认情况下系统创建拷贝构造函数是浅拷贝 有可能的错误 一般使用不会出错但是如果数据是程序员开发在堆区就会发生释放重复的错误 错误原因 因为浅拷贝使两个对象里的属性指向同一块空间当释放一个对象中的属性之后再去释放另一个也在堆区的数据由于她们指向相同所指向的空间已经被释放但是系统不知道因此会发生错误 解决方案 改进方法就是进行深拷贝程序员自己创建一个函数来达到深拷贝的效果深拷贝是在拷贝构造函数内进行自己再开辟一片空间只复制要拷贝对象属性的内容而非空间地址。 深拷贝和浅拷贝案例 #includeiostreamusing namespace std; class person{public://创造构造函数person() {cout 默认构造函数 endl;}person(int age,int height) {Age age;high new int(height);cout 有参构造函数 endl;}person(const person a) {Age a.Age;cout person的拷贝构造函数 endl;highnew int(a.high);}~person() {//析构代码将堆区开辟数据做释放操作if (high ! NULL) {delete high;high NULL;}//加上这个代码后运行发现程序崩溃了cout 析构函数调用 endl;}int Age;int high;//身高使用指针把这个参数存放在堆区//堆区的数据由程序员手动开辟也由程序员手动释放销毁前释放在析构之前释放 }; void test1() {person p1(18,160);cout p1年龄 p1.Agep1身高为*p1.high endl;person p2(p1);//编译器创建了一个拷贝函数进行了一个浅拷贝的操作简单的赋值操作逐字节拷贝cout p2年龄 p2.Age p2身高为 *p2.high endl;//栈区先进后出所以p2先被释放p2先执行析构函数p2释放过了指针所指的内存则再次用p1释放时发生错误//解决浅拷贝用深拷贝改进不是逐个字节拷贝了是重新开辟一个空间两个空间就不会存在重复释放了//自己写拷贝构造函数 } int main() {test1();system(pause);return 0; } 初始化列表 简介 初始化类中属性1创建构造函数2.初始化列表 构造函数属性1值1属性2值2 基本初始化列表案例 #includeiostream using namespace std; //初始化列表//初始化类中属性1创建构造函数2.初始化列表// 构造函数属性1值1属性2值2 class person{public://初始化列表给类属性赋初值person() :Age(10),b(20){}int Age;int b; }; void test1() {person p1;cout p1.Age \t p1.b endl; } int main() {test1();system(pause);return 0; } 灵活定义初始化的数字时的初始化列表案例 #includeiostreamusing namespace std; //初始化列表//初始化类中属性1创建构造函数2.初始化列表// 构造函数属性1值1属性2值2 class person{public://初始化列表给类属性赋初值person(int a,int n) :Age(a),b(n)//注意这个冒号的位置别写错了{}int Age;int b; }; void test1() {person p1(12,22);//12先传给了p1中的int a然后传入到Age里的a,这样Age就被这个数字赋值了被初始化了。cout p1.Age \t p1.b endl; } int main() {test1();system(pause);return 0; } 类对象作为类成员 类定义的对象称为另一个类里的成员则称为类成员 构造顺序和析构顺序相反 构造时先构造类成员的类再构造类成员所在的类 而析构顺序则正相反。 #includeiostream #includestring using namespace std; //类对象成为另一个对象的成员称为类成员 //先有的什么先构造其他的类的对象再构造这个类 //那么析构的顺序呢和构造的顺序是相反的。 class A { public:// 可以用Phone a_phonepname隐式转换法来初始化变量A(string Name, string pname):name(Name),a_phone(pname){cout A的构造函数 endl;}//姓名string name;//手机Phone a_phone;//类成员 }; //手机类 class Phone{ public:Phone(string pname) {//Phone 的构造函数Pname pname;cout Phone的构造函数 endl;}//手机品牌名string Pname; }; void test1() {A p(黑菜钟,华为);cout 名字:p.name endl;cout 手机型号: p.a_phone endl;} int main() {test1();system(pause);return 0; } 静态成员 定义静态成员就是在成员变量和成员函数前加上关键字static称为静态成员 分为静态成员变量和静态成员函数 静态成员变量要求所有对象共享同一份数据编译阶段分配内存类内声明类外初始化 静态成员函数要求 静态成员变量 静态成员变量示例 当静态成员变量像平常一样定义类对象并且输出所对应的值的时候程序会怎么样 结果发生错误无法解析的外部命令这是因为静态成员变量要类外进行初始化操作这个程序显然没做 如何在类外初始化呢int person::m 100;这里的person是类名m是类内静态变量 静态成员变量访问案例 ⭐静态成员变量不属于某个对象所有对象共享同一份 访问方式 1.通过对象访问person p;coutp.m_Aendl;2.通过类名访问cout person::m_A endl; #includeiostream #includestring using namespace std; //静态成员变量 //所有对象共享同一份数据 // 编译阶段分配内存 // 类内声明类外初始化 class person { public:static int m_A;}; int person::m_A 10; void test1() {person p;cout p.m_A endl;//10person p2;p2.m_A 20;cout p.m_A endl;//结果为20因为所有对象共享数据一改全改//静态成员变量不属于某个对象所有对象共享同一份 } void test2() {//访问方式1.通过对象访问person p;coutp.m_Aendl;//20//访问方式2.通过类名访问cout person::m_A endl;//用::来借助访问类对象 }int main() {test1();test2();system(pause);return 0; } 注意静态成员变量只能在公共权限内定义在私有权限内定义不出错但是不能共享数据。类外访问不到私有静态变量。 静态成员函数 特点所有对象共享同一个函数静态成员函数只能访问静态成员变量 静态成员函数创建调用基本示例 #includeiostream #includestring using namespace std; //静态成员函数 //所有对象共享同一个函数 // 静态成员函数只能访问静态成员变量class person { public:static void func() {cout static void func调用 endl;} };void test1() {//访问方式和静态成员变量的访问方式相同//1.通过对象person p;p.func();//2.通过类名person::func(); }int main() {test1();system(pause);return 0; } 如果静态成员函数访问非静态成员变量会出现这样的结果 why? 数据属于特定的而函数体无法区分是哪个对象的会出错 而静态成员变量是共享的所有类的对象都用一份函数体不需要知道这是哪个类对象对应的 ⭐注意 类外还是不可以访问私有的静态成员函数 结语 希望这篇有关c对象初始化和清理的博客对大家有所帮助欢迎大佬们留言o()ブ 一起学习进步