撤销和重做(Undo和Redo)的C++完美实现(6)

本文介绍了如何在C++中处理复杂(复合)对象的撤销和重做操作,特别是当对象包含指向其他对象的指针时。通过使用标识符类对象替代指针,讨论了如何在创建、修改和删除操作中优化资源使用,以减少空间和时间开销。示例代码展示了如何为复合类实现撤销和重做功能,强调了模板元编程在自动化编码中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#if 0

在前面的章节中我们讨论的对象都是简单对象,那么什么是简单对象呢?关于这个问
题,首先还是先关注一下C++语言里面的基本类型。C++语言里面的基本类型如下:

char (signed,unsigned)
int (signed,unsigned)
short (signed,unsigned)
long (signed,unsigned)
float,double

对于这里的基本类型就是简单对象的特殊形式,实际上只要具备有和这些基本类型相
同性质的类都是简单类,相应的对象就是简单对象。实际上这里主要是拥有了拷贝语义:
也就是具备有深度拷贝语义的类,这些类通常都具备有拷贝构造函数,赋值运算符。如此
说来,STL里面的string也是简单类,相应的对象也是简单对象,前面的Circle类和
Rectangle类都是简单对象;当然简单类里面不一定非要明确的写明拷贝构造函数和赋值运
算符,这些工作编译器会为我们自己添上的,我们不必操心。

好了,讨论了简单对象之后,应该讨论一下和简单对象相对的复杂对象了,这里的复
杂对象也可以称为复合对象。这里的复合对象就是和简单对象相对的必须自己添加拷贝构
造函数和赋值运算符的类对象。通常来说,这种对象含有指向其它对象的指针,在前面已
经提到:在本类文档中尽量的避免使用指针,为的就是简化编码,提高安全性,所以这里
将会用前一章中给出的标识符类对象来代替指针。这也是这一篇文章的中心内容!

在讨论复合对象之前首先需要给出复合对象出现的背景和需要解决的问题:

前面的简单对象的撤销和重做的备份信息都是备份了整个对象,如果这个简单对象的
尺寸不大,当然没有什么问题,但是实际的情况是,程序中经常会出现很多的对象中还包
含了指向其它对象的指针,这样如果对这个对象采用深度拷贝语义的话,在创建和删除操
作的时候可以备份完整的对象信息,因为所有的信息都是必须的。但是当执行修改操作的
时候,仅仅只是为了修改复合对象的一个属性就需要备份整个复合对象,这样就太浪费空
间和时间了,要知道,本类文档所讲的撤销和重做机制就是为了减少撤销和重做的空间和
时间开销,同时简化编码;为了解决这个问题从而引入了复合对象的概念。

在正式介绍复合对象之前先来看一段示例代码,以解释简单对象和复合对象的概念:

#endif
#ifdef CODE_NOTE
//矩形类(简单类)
class Rectangle
{
public:
int x,y,width,height;
};
//圆形类(简单类)
class Circle
{
public:
int x,y,radius;
};
//(a)圆角矩形类(简单类)
class RoundRectangle
{
public:
Rectangle _rectangle;//矩形
Circle _circle[4];//四个角上的圆角
};
//(b)圆角矩形类(复合类)
class RoundRectangle
{
public:
Rectangle*_rectangle;//矩形
Circle *_circle[4];//四个角上的圆角
};

#endif//CODE_NOTE

#if 0

从上面的代码中我们可以看出矩形类(Rectangle)和圆形类(Circle)都是简单对象,因
为它们的成员变量都是基本类型的,所以不必明确写出拷贝构造函数和赋值运算符。对于
圆角矩形的a方案,也是个简单类,因为它的成员都是简单类型,也不必明确写出拷贝构造
函数和赋值运算符,编译器会为我们添上。现在我们就来认真考虑圆角矩形的b方案了,很
显然b方案中的成员变量都是指针类型,实际上只要有一个成员是指针类型该类型就成为了
复合类型了,因为它的拷贝构造函数和赋值运算符必须有我们添上,编译器默认的拷贝构
造函数和赋值运算符仅仅只是拷贝了指针值而已,因而不符合我们的要求。

对于a方案,因为这个圆角矩形也是一个简单类,所以和前面的矩形类和圆形类在撤销
和重做机制上没有任何的区别,矩形类和圆形类怎么编码,a方案的圆角矩形类也怎么编码
。但是我们注意到简单类的撤销和重做的过程中备份的信息都是整个对象进行备份,那么
在创建和删除a方案的圆角矩形类的时候,备份整个对象是必须的,信息没有冗余,但是仔
细考虑一下当我们仅仅只是修改一下a方案圆角矩形类对象的一个圆角,那么这个修改操作
将会备份整个圆角矩形类对象,这里面将会备份额外的一个矩形对象和另外三个圆角上的
圆对象,很显然这是一种空间上和时间上的浪费。

为了解决这个问题,实际的应用中需要用到很高深的模板元编程技巧,通过模板元编
程来实现C++程序的自动化编码,可以参见本人的另外一篇文章“自动化C++编程”。但是
为了本篇文章的简单性,在这里仅仅采用宏来实现专有的功能,如果要将本文的宏实现能
够以库的形式提供,那么必须通过模板元编程来实现,这一点在“自动化C++编程”文章
中解释!

已经铺垫了这么多,现在终于可以开始讨论本篇文章需要解决的问题了:

对于上面的b方案的复合类怎么实现撤销和重做功能。

下面是解决这个问题的示例代码:(代码中用标识符代替了指针)

#endif

#ifdef CODE1
#include <iostream>
#include <algorithm>
//下面的三个头文件都是前面章节中已经给出了的代码,直接复制出来保存到指定的文件
//中即可
#include "command.h"
#include "center.h"
#include <
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值