复制控制例子 --参照《C++ Primer》第415页消息处理示例
一.场景:
两个类:
Folder类:
表示一个目录,有一些指针成员指向该目录下的文件
File类:
表示一个文件,
(1)有一个string成员存储文件内容
(2)有Folder类型的成员指针集指向存有该文件的目录
(3)有一个save()和remove()方法分别用于保存和移动。
功能:(1)在创建的时候传入文本初始化文件的文本
(2)在保存的时候传入目录指定文件所在的目录 (可保存在多个目录)
(3)要求能复制、赋值、删除文件类
如图:(简化)
二.数据结构
1.Folder类: 只要有一些 指向 File类的指针即可
2.File类: set <Folder*>:指针集来存储所在的目录
string content :存储文本内容
三.分析File类
1.功能:(考虑文件和目录之间的指针处理)
(1)写入内容(content):创建的时候
(2)保存文件类:保存在某个目录下
(3)复制文件类:在所有包含该文件的地方都要求有文件的副本
(4)删除文件类:在所有包含该文件的地方都要删掉
2.特性:
可保存在多个目录下,文件类记录了所在的目录。多个目录指向的是同一个文件。
(考虑文件和目录之间的指针处理)
3.功能实现:(文件和目录之间的指针处理)
(1)写入内容:(形参:内容)(构造函数实现)
创建File类的时候写入内容,但是不指定在哪个目录(未保存)
(2)保存(形参:目录)
将file 类存入指定的目录FolderA中。在file类中的set<Folder*>添加FolderA,并在FolderA中添加指向该file类对象的指针。
(3)删除文件类
1. 要把包含B的目录中把指向B 的指针释放,还有B指向目录的指针也要释放掉
如图:
(4)复制文件类(A 复制 到B(B 原先不存在))
1.复制类成员(content , set<folder*> )到新对象 (合成的复制构造函数做的事情)
2.对set<folder*>中的 每一个folder*(目录)都必须添加一个指向新对象的指针
(合成的复制构造函数不会做这一步)
如图:
\
(5)赋值文件类(A复制到B(B原先存在))
2.要把包含B的目录中把指向B 的指针删掉,还有B指向目录的指针也要释放掉(删除操作
3.把A 的成员赋值给B(文本内容和指针集合) -
4.包含了A 的目录要添加指向B 的指针(现在目录可以从B 的新的指针集合中获取)(复制操作)
可以看到:赋值操作是由删除(1)和复制(2、3)的操作合成的。
四、实现File类
1、从前面的分析可以看到
删除操作 --》析构函数
复制操作--》复制构造函数
赋值操作--》赋值操作符
用到了复制控制的三个函数,而且编译器合成的函数无法满足需求,所以要用户自定义这三个函数。(注意,自定义析构函数后还是会调用合成的析构函数)
2、实现:
定义类File成员: string content, set<Folder*>folders;
定义两个private函数:(注意赋值操作用到了删除和复制,所以删除和复制各用一个 private函数实现,以便多个成员函数调用)
Put_File_In_Folder(const set<Folder*>folders);//把文件加入到相对于的目录集
Remove_File_From_Folder();//从包含文件的目录集中删除该文件对象
(1)析构函数:(对应删除操作)成员的释放由自动调用的析构函数完成
File::~File()
{
Remove_File_From_Folders();
}
(2)复制构造函数(复制操作)
File::File(const File &m)
content(m.content),folders(m.folders) //初始化列表
{
Put_File_In_Folder(folders); //为目录集添加指向该类的指针
}
(3)赋值操作符重载(赋值操作)
File & File::operator = (const File &rhs)
{
If (&hrs != this)
{
Remove_File_From_Folders(); //删除原来的指针
Content = rhs.content;
Folders = rhs.folders;
Put_File_In_Folder(folders); /为目录集添加指向该类的指针
}
}
五、心得:
要根据实际情况来判断是否要自定义复制控制操作,同时赋值操作符通知要做复制构造函数和析构函数要完成的工作,所以可以把通用的工作放在private函数中。