| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> (C++)构造函数,类成员的屏蔽与作用域,参数初始化列表,访问权限,复制构造函数,深复制与浅复制课堂作业 -> 正文阅读 |
|
[人工智能](C++)构造函数,类成员的屏蔽与作用域,参数初始化列表,访问权限,复制构造函数,深复制与浅复制课堂作业 |
1.构造函数 ????????构造函数用于在创建对象时赋给对象初始值,它的函数名与类名相同,没有返回值。它可以被重载,即可以编写多个参数存在一定差异的同名的构造函数。当没有自己编写构造函数时,编译系统将提供一个默认的构造函数,它没有参数,不执行任何语句。 ????????编写的构造函数若没有参数,应如下图student a这样创建对象,调用的是第一个构造函数。注意student a();表示的是声明了一个返回值为student类型的函数a。若有参数,则如主函数中第二条语句student ?b(2200)这样创建对象并传递初值。 ????????不妨将student的成员变量增加性别与姓名,得到更加复杂的构造函数。后续题目将在student类的基础上讲解。 2.类成员的屏蔽与作用域 ????????类的成员变量,如图中student类中的num,sex,name,无论是在类开始还是类结束时定义,其作用域都是本类中,可以被本类的所有成员函数使用。在程序结束时,或非动态创建它的函数结束时,或释放此类对象动态申请的内存时,其生存期结束。如果成员函数的形参与成员变量的名字相同,在本成员函数中,同名的成员函数即被屏蔽。如果仍想这样统一命名,可以使用this指针,它是隐含在每个成员函数中的指向当前操作该成员函数的类的对象的指针,用法与结构体指针类似。 3.成员初始化列表(参数初始化列表) ????????除了通过构造函数对对象进行初始化,还可通过参数初始化列表对其进行初始化。修改后的student类的构造函数: ????????使用参数初始化列表,可以像这样同名而不使用this指针,可以将一部分或所有的初始化像这样在函数的首部实现。 ????????但当某个成员函数声明为常量时,它就不可以在构造函数的函数体里赋值,必须在参数初始化列表里赋值。前者就像const int i;i=5;而后者就像const int i=5;假设每个学生都有一个不变的身份识别码id,修改后的代码: 4.public,protected和private(访问权限) ????????类中有三种访问权限:public,protected和private,目的是做到信息隐藏。访问权限是相对于类来说的,而不是相对于对象来说的。声明为private权限的成员,只可被本类的成员函数所访问,如在类外直接用 “对象名’.’成员变量名”是非法的,是没有访问权限的。而声明为public权限的成员就没有这个限制,可以在类外直接访问。当成员没有声明访问权限时,默认其为private;当声明了访问权限时,从声明到下一次声明或类定义结束,都是此访问权限。 ????????对于private权限的成员变量,不去直接修改它的值,而是通过public权限的成员函数来间接修改,这是面向对象程序设计的重要思想。如: ? ? ? ? 主调函数加上: 5.copy constructor(复制/拷贝构造函数) ????????复制构造函数可以用一个已有的对象复制出多个完全相同的同类对象。这里的“复制”指的是从无到有的创建一个对象,如int a=b;不同于“赋值”是对一个已存在的对象赋值,如int a;a=b; ????????复制构造函数不同于一般的构造函数,它的形参是对象的引用,一般加上const声明避免实参被意外修改。如: ????????调用复制构造函数时,可以写成以下两种形式: ????????如果没有自己设置复制构造函数,编译系统将提供一个默认的复制构造函数,作用是简单的复制类中的每个数据成员。即如果以上第3条语句的复制构造函数没有写出,依然可以像主函数里这样使用。 Q:普通的复制构造函数在建立对象时调用,那么什么时候会调用复制构造函数呢? ①建立一个对象,并用另一个同类对象对其初始化,如以上的student b(a)和student c=a。 ②函数的参数为类的对象,在传值的时候需要创建这个形参对象,并用实参对其初始化,故也需调用复制构造函数。如: ?????????如果实参是student的对象b,相当于student a=b; ????????由此引出一个问题:为什么复制构造函数的形参是引用而不是普通的值传递呢?不妨假设student类的复制构造函数是普通的值传递,如: ????????在用对象a复制b时(student b=a),又需要用实参a复制出形参stu(student stu=a),调用stu的复制构造函数,stu的构造函数用需要用a复制新的stu......如此循环,结果只有内存溢出。故复制构造函数的形参是对象的引用是很合理的 ③函数的返回值是类的对象。如: ????????返回的对象b,在赋值给主调函数里的对象a前需要另外赋值一个对象c,因为返回的对象b在函数f结束时需要内存释放,而赋值是在b内存释放后进行的,赋值结束后c的内存也释放掉。 6.Deep copy or shallow copy(深复制/拷贝与浅复制/拷贝) ????????如果只是想将类中的成员简单的赋值,并不需要自己写出复制构造函数,用编译器给出的默认的复制构造函数即可(浅复制)。但如果类中的成员变量需要动态开辟堆内存,就需要用到深复制构造函数。如: ????????先来看普通的复制构造函数(第三个)会产生的问题,不管是自己写出还是编译器默认,都只是将类中的成员变量的值简单的进行赋值。如果已建立对象a: ????????则对象a的成员变量name中存放的是字符串常量“faker”的地址。当因某些原因将a或以a为副本复制出的对象b、temp进行内存释放后,a与b中name的值不变,还是“faker”的地址,但原本储存“faker”的内存已经被释放掉了,如此一来,所有对象的name便成为了野指针。 ????????因此我们使用深复制构造函数处理类似的情况。具体来说,就是在重写复制构造函数时对某些成员变量特殊处理。如: ????????在完成num的赋值后,name指向新开辟的一块长为传入字符串长度+1的内存,在用strcpy将stu的name指向的值复制给这块内存,即分别指向两份独立的“faker”。如此,在将对象a内存释放后就不会影响对象b。 ????????这种对一个拥有资源的类进行复制对象时,资源重新分配的过程叫做深复制,而不重新分配资源的叫浅复制。我们在5题中重写的复制构造函数,和编译系统默认提供的复制构造函数都是浅复制,本题中重写的是深复制。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 8:26:29- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |