为C++类设计,以撤消对另一个类成员的修改
Design for a C++ class to undo modifications to another class member
我有一个设计繁琐的对象组合。类别X和Y是该设计的示意图,其中Y是X.的一个组件
class Y {
public:
std::string _name;
Y(std::string name) : _name(name) {}
};
class X {
Y _y;
public:
X(std::string name) : _y(name) {}
Y getY() { return _y; }
Y* getYPtr() { return &_y; }
};
注意,Y
中的std::string _name
是公共的。
我想做的是通过X
的实例访问Y::_name
,为其写入新值,并有可能在程序的其他部分轻松撤消写入操作。
我的尝试如下:我使用一个Undo
对象,它包含三个信息:
- 指向撤消生效的字符串的指针
- 包含旧名称的字符串
- 包含新名称的字符串
class Undo {
std::string _oldName;
std::string _newName;
std::string *_internalName;
public:
Undo(std::string *name) : _internalName(name) {}
void setOldName(std::string oldName) {
_oldName = oldName;
}
void setNewName(std::string newName) {
_newName = newName;
}
void undoToOldName() {
*_internalName = _oldName;
}
};
如果我想撤消写操作,我只需要调用Undo
对象上的undoToOldName()
方法。
示例:
X x("firstName");
Y *y = x.getYPtr();
// Prepare the undo object
Undo undo(&(y->_name));
undo.setOldName(y->_name);
undo.setNewName("secondName");
// Set new name
y->_name = "secondName";
// Output: secondName
std::cout << x.getY()._name << std::endl;
// Undo
undo.undoToOldName();
// Output: firstName
std::cout << x.getY()._name << std::endl;
我不喜欢这种设计的一点是需要Y *
getter。
作为约束,我不能改变作文的设计。
你能为这个提出替代设计吗?
谢谢。
使用对象修饰符保护修订的不变性异常棘手。如果您需要同时回滚多个字段,而其中一个字段失败,您该怎么办?您的修订控件实际上也可能影响对象的正常操作。
对对象进行版本化的一个简单方法是保留对象的所有版本。当您需要回滚时,只需将其替换为旧版本的副本。
一些注释:Undo
对象不应该需要setOldName
方法。它可以计算出来,因为它有字符串指针。其次,它也不需要setNewName
;它只需要一个方法来告诉它何时设置新值。(假设你需要它,我对此表示怀疑)
一个不错的设置是让getYPtr()
返回一个undo_ptr<Y>
。这是一个薄垫片,它知道相关的Undo
对象。当调用undo_ptr<Y>::~undo_ptr
时,即当客户端完成时,调用关联的Undo::newNameSet
方法。如上所述,这只是通过提供的指针提取新值。
示例:
X x("firstName");
{
Undo undo(x, &X::name); // Slightly cleaner interface. Saves "firstName".
Y* y = x.getYPtr();
y->_name = "secondName";
// Output: secondName
std::cout << x.getY()._name << std::endl;
// Undo (calls Undo::operator(), the convention for functors).
undo();
// Output: firstName
std::cout << x.getY()._name << std::endl;
}
正如您所看到的,在这种情况下不需要捕获新名称,因此您不需要undo_ptr<Y>
的框架。
为什么要创建一个新类?您可以使用beginTransaction
、commitTransaction
和rollbackTransaction
方法扩展类X
,以及一个update
方法,如果在事务外调用该方法,该方法将可选地断言。
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 无法将指向类的成员函数的函数指针作为参数传递给同一类的另一个成员函数
- 访问从联合与另一个成员集复制的联合中的一个成员是否未定义或未指定?
- 使用线程从另一个成员函数调用一个Member函数
- 如何通过指针将模板成员函数传递给另一个成员函数
- 初始化指针或引用成员变量以指向另一个成员
- 在另一个成员函数中调用成员函数时'int'之前的预期主表达式
- C 将成员函数作为参数传递给另一个成员函数
- 如何在另一个成员函数中修改具有常量返回类型的成员函数的返回值
- 从其后声明的另一个成员数据初始化成员数据是否为未定义行为
- 如何使一个成员变量等于在main()中设置的另一个成员变量
- 在另一个成员中动态添加类成员
- 将类成员函数作为参数从同一类的另一个成员函数传递
- 将成员函数指针作为另一个成员函数中的参数发送
- 如何从同一类的另一个成员函数调用函子
- 从另一个成员函数的实现调用成员函数
- 如何将带有 args 的成员函数作为参数传递给另一个成员函数
- C++ 成员函数错误 在另一个成员函数中使用时"Undeclared Identifier"
- 如何根据其中一个成员的值对结构数组进行排序,从而在另一个成员的基础上断开联系
- 初始化整数成员变量会导致更改另一个成员变量的地址