(课件)-一、浅拷贝和深拷贝二、只读成员函数三、友元friend

上传人:繁星 文档编号:88149314 上传时间:2019-04-20 格式:PPT 页数:38 大小:142.60KB
返回 下载 相关 举报
(课件)-一、浅拷贝和深拷贝二、只读成员函数三、友元friend_第1页
第1页 / 共38页
(课件)-一、浅拷贝和深拷贝二、只读成员函数三、友元friend_第2页
第2页 / 共38页
(课件)-一、浅拷贝和深拷贝二、只读成员函数三、友元friend_第3页
第3页 / 共38页
(课件)-一、浅拷贝和深拷贝二、只读成员函数三、友元friend_第4页
第4页 / 共38页
(课件)-一、浅拷贝和深拷贝二、只读成员函数三、友元friend_第5页
第5页 / 共38页
点击查看更多>>
资源描述

《(课件)-一、浅拷贝和深拷贝二、只读成员函数三、友元friend》由会员分享,可在线阅读,更多相关《(课件)-一、浅拷贝和深拷贝二、只读成员函数三、友元friend(38页珍藏版)》请在金锄头文库上搜索。

1、1,一、浅拷贝和深拷贝 二、只读成员函数 三、友元friend,第16章 数据的共享和流通,2,一、浅拷贝和深拷贝 对象作为数据的集合,其中有些数据需要与变 量进行流通,有些数据需由不同的对象共享。 本章介绍的深拷贝、友元函数、静态成员和指 向成员的指针就是在不同的方面加快信息流动以及 实施对象的保护的。,3,存在两种形式的类。 一种形式的类中仅存在变量或对象,不具备指 针成员。缺省的拷贝构造函数和赋值运算符函数是 浅拷贝的方式,该方式通过memcpy函数将源实例 的数据复制给目标实例占住的一片内存空间。 对于这样的类,缺省的浅拷贝方式是安全的。 另一种形式的类含有指针成员,浅拷贝不再胜 任这

2、样的类。,4,考虑如下说明: 从上可见对于存在指针成员的类,系统提供的浅拷贝导 致指针指向的内存为两个对象共享的格局。,一个CDeep类的声明和对象定义,对象a,b的内存和指针成员动态扩展的内存空间b=a导致 b.p=a.p; b.n=a.n; 。指针b.p指向a对象的动态内存。,class CDeep int n; int*p; a, b;,中间深资源归口两个对象监控,5,浅拷贝的不良结果是:b.p原先指向的堆空间悬空-既 无法索引也不能收回这片内存,a或b对象的析构函数诱发中 间共享的深资源的流失。 对于凡是具有指针成员的类,应细致提交两个函数: 一.是拷贝构造函数, 二.是赋值运算符函数

3、,以便进行指针成员的动态资源 的深拷贝。 深拷贝的核心思路是: 1. 目标对象与源对象内存空间独立,相应指针成员指 向的内存空间也彼此独立。 2. 全部拷贝源对象的数据到目标对象,包括分别拷贝 指针成员指向的内存数据。,6,例 深拷贝方式(去掉定制的拷贝构造函数和赋值运算符函 数则变成缺省的浅拷贝) #include #include class CDeep public: int n; int *p; CDeep (int) ; CDeep (); CDeep (const CDeep,7,CDeep:CDeep() static int s_num=1; printf (“%d.CDeep

4、 ()t“, s_num+); delete p; CDeep:CDeep (int k) n=k; p=new int n; CDeep ,8,CDeep:CDeep (const CDeep ,9,程序输出: 88;1.CDeep() 666;b fade out away; 88; 2.CDeep() 3.CDeep() 删除上面的拷贝构造函数和等号赋值运算符函数时,程 序运行输出: 88;1.CDeep() 666;b fade out away; -572662307;2.CDeep() 3.CDeep() 之后弹出一个Debug Assertion Failed!的警告对话框。 原

5、因在于b对象退出作用范围后导致析构函数的调用, 析 构函数释放原来由a对象拥有的深部堆中资源,其后对该内 存空间的操作 a.d0就等于在没有定义的内存空间进行寻址 访问,因而是运行时的错误。,10,二、只读成员函数volatile, mutable关键字 1. 只读成员函数 未经const或volatile限制的对象或成员函数是普通的 对象或普通的成员函数,依称为对象或成员函数。 只读对象是关键字const限定的对象。只读成员函数是 const置于成员函数右圆括号之后修饰的成员函数,该成员 函数不修改成员变量的数据状态,即成员函数体中出现的数 据成员仅作为右值。 没有只读的构造函数和析构函数,

6、只读对象和对象都调 用同一构造函数和析构函数。,11,const用于名称细分,成员函数声明和定义都必须紧跟 const关键字。 只读成员函数的声明和定义格式为:(其中type,t1, t2,tn是已经声明的类型) type f (t1 v1, t2 v2, .,tn vn) const; type CType: f(t1 v1, t2 v2, .,tn vn) const ; .; 成员函数可存在两个重载版本: 一个只读版本另一个普通版本。 当两种版本并存时,对象优先调用普通的成员函数,只 读对象或只读的对象引用仅仅调用只读成员函数。,12,对象可调用只读成员函数。关键字const本质上约束

7、this形参为只读属性。 只读指针形参可以匹配左值区的地址,普通指针形参不 指向右值区的地址。 只读对象的地址是右值区的地址。 只读对象和只读成员函数不调用普通成员函数。普通的 成员函数可调用只读成员函数。 只读成员函数是只读取对象的数据状态的成员函数。,13,例 const对象与只读成员函数。 #include struct CPoint long x; long y; ; class CRect public: CRect (int l, int t, int r, int b) ; CPoint ,14,inline CPoint /输出:left=10,top=20 left=15,t

8、op=25,15,成员函数TopLeft存在只读的和非只读的版本,其中的 语句是一样的。 返回引用的函数可以作为左值,本来只读成员函数不改 变对象的数据状态,如果不在返回类型上加const限制将导 致对象外部调用对数据的改变。 于是返回引用的只读成员函数在返回类型上由const前 置限制。 d.TopLeft ()为只读对象d调用只读成员函数。 r.TopLeft ()为对象r调用普通的成员函数。,16,2. volatile关键字 volatile关键字表示内存数据的变更。 volatile关键字和const关键字的语法是一致的。 const修饰的变量维持恒定或函数不改变相关成员的数 据状态

9、。 与const相反,volatile关键字限定的对象或成员函数 可以有效的变动。 这种变动可以来自其它的外部进程。,17,例 volatile关键字的用法 #include class B volatile int m_n; public: B (int v=1) m_n=v; void Set (int n) volatile m_n=n; void Show () const printf (“Show()const; n=%dn“,m_n); void Show() volatile printf (“Show() volatile; n=%dn“,m_n); void Show()

10、printf (“Show() ;n=%dn“,m_n); ;,18,void main() const B c; c.Show(); volatile B v(2); v.Show(); v.Set(3); v.Show(); B x(4); x.Show(); ,/*程序输出结果: */ /*Show() const; n=1 */ /*Show() volatile; n=2*/ /*Show() volatile; n=3 */ /*Show() ; n=4 */,19,volatile对象操作volatile成员函数, const对象操作 const 成员函数。不妨认为volatil

11、e关键字和const关键字是 一对含意相反的语法修饰词,它们常称为c-v限定词。 对象既可操作const成员函数也可操作volatile成员函 数,如果这两个成员函数都存在但不存在普通的版本则导致 调用的歧义。 volatile关键字使用的场合在一般程序中不 多,主要用在系统的程序设计中。 volatile关键字可以和const同时出现。如下: volatile const int g_n=1; 这表示程序不能改变变量g_n的值,但允许系统改变它。,20,3. mutable关键字 关键字mutable可以局部松动const对象的不变属性。 如果一个对象前加上const关键字限制,则这个对象所

12、 有的成员就冻结为右值。 但有时候对于这种约束期望有所放松,此时只需在相关 的成员前冠以mutable修饰,通知编译器如此成员不受 const的制约。,21,例 mutable关键字注册绝对可变的成员 #include class CType public: mutable long v; long n; ; void main() const CType cobj=1,2; printf (“cobj=%d,%d; t“,cobj.v,cobj.n); cobj.v=8; printf (“cobj=%d,%d;n“,cobj.v,cobj.n); /cobj.n=2; error : l-

13、value specifies const object /输出结果:cobj=1,2; cobj=8,2;,22,上面的代码中v是一个绝对可变的成员。 n是一个相对可变的成员,n受const对象限制时而间接 的成为右值表达式。 对于本题cobj是一个不变对象,因而cobj.n不能成为左 值,v由于有了mutable的特殊关照,cobj.v则构成左值表达 式。,23,三、友元friend friend声明的函数称为友元函数,friend 可用于声明一 个类,这个类称为友元类。 友元函数细分为全局友元函数和成员友元函数。友元函 数或友元类在所访问类或当前类中由friend声明。格式为: clas

14、s CN private: friend T f (T1, CN /类型名称type,T, T1, T2, ,Tn, A, B在使用点之前 应首先说明,24,friend关键字无视protected,private的制约,放置在类 声明的任何地方是等效的。 友元可访问当前类的所有成员。友元类所有的成员函数 都是友元函数。 友元类或友元函数一般通过三个途径访问当前类所有的 成员,包括公共属性的保护属性的和私有属性的成员: a. 友元函数的入口形参具有当前类的类名。 b. 友元函数具有当前类的对象作为局部对象或对象指针 作为局部指针。 c. 友元类具有当前类的对象作为其嵌入成员对象。,25,1.

15、友元函数 友元函数是一种定义在当前类外部的普通函数,通过 friend在当前类内部声明,但友元函数不是当前类的成员函 数。 在当前类的友元函数获得如此特权: 定义在友元函数形参列表或函数体中的当前类对象、对 象引用或对象指针等可以访问该类所有控制属性的成员包括 私有成员,就好像当前类三个访问控制属性全部是公共的访 问控制属性。,26,友元是一种解除访问控制约束的机制。 此种破除访问控制约束的友元关系不传递不反身不继 承,即如果类A是类B的友元, 类B是类C的友元,A不会自动 称为类C的友元; 类A是类B的友元但不一定类B是类A的友元; 类A是类B的友元, 类A的派生类D不会自动成为类B的 友元。 友元函数是某个类的特权函数,这个访问当前类所有成 员的特权在该类中由friend声明获得,未由friend声明的函 数操作当前类的公共成员。,27,例 友元函数将类回归到经典的公共访问性质的结构 #include struct S int e; class B; class A private: int a;

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 工作范文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号