我正在编写一些相关的C ++类,而且我在设计特定的继承函数时遇到了一些麻烦。
具体来说,这些类都是树上的“操作”,我需要能够在树上执行一组任意树操作。我在每个类中都有一个名为ExecuteOperation()的函数。
问题在于,在某些课程中,我需要比其他课程更多的补充信息。现在,我只是将额外的信息传递给所有类,其抽象基类定义如下:
class BasicOperation {
public:
//...
virtual void ExecuteOperation(Tree* tree, multimap<int,Foo*> extra1, multimap<int,Foo*> extra2) = 0;
//...
}
BasicOperation子类的后代“SpecialOperation”需要参数extra1和extra2,而“NonspecialOperation”的后代根本不使用这些参数。
ExecuteOperation的调用者通常是这样的:
Tree* tree;
std::vector<BasicOperation*> operations;
//...
for(size_t i=0;i<operations.size();i++) {
operations[i]->ExecuteOperation(tree,extra1,extra2);
}
extra1和extra2的填充取决于特定的树,可能是计算密集型的(最好不要在每次ExecuteOperation调用中重新创建它们)。
有没有更好的方法来设计它,以便只有SpecialOperation对象获取传递给它们的参数?或者将未使用的参数传递给像NonspecialOperation这样的类一样好吗?
使用两个不使用的参数定义NonspecialOperation :: ExecuteOperation()感觉很奇怪。
到目前为止,我唯一想到的是将SpecialOperation对象的每个指针都返回给调用者,并将额外的信息存储在调用者对象中。我真的不喜欢这个解决方案,因为extra1和extra2太依赖于当前的状态;除了并行化问题,这种设置只是“感觉”错误。
另外,将tree,extra1和extra2包装在另一个结构中以传递给ExecuteOperation可能会使它看起来更干净,并且有意义,因为extra1和extra2是树的额外描述符,但我不知道这是否是最佳解决方案:
struct TreeEx {
Tree* tree;
multimap<int,Foo*> extra1, extra2;
};
//in BasicOperation:
virtual void ExecuteOperation(TreeEx* tree_with_info) = 0;
答案 0 :(得分:3)
使用
virtual void ExecuteOperation(Tree * tree);
没有额外的论据。
在BasicOperation
派生的类中通过构造函数传递额外的参数。
向树添加允许BasicOperation
提取所需数据的方法。
- 编辑 -
额外的参数特别适用于树
在基础Tree类中创建一个虚拟函数,用于创建所需的命令
class Tree{
public:
virtual BasicOperation* makeSpecificTreeOperation() = 0;
virtual ~Tree();
};
在儿童中重写
class DerivedTree: public Tree{
...
virtual BasicOperation* makeSpecificTreeOperation();
...
};
class DerivedCommand: public BasicOperation{
....
public:
DerivedCommand(ExtraTreeData& extraData);
};
BasicOperation* DerivedTree::maksSpecificTreeOperation(){
return new DerivedCommand(this->extraData);
}
并返回所需的命令类,使用构造函数将数据传递到命令中。
请参阅Abstract Factory模式和Builder模式。
答案 1 :(得分:1)
如果是通过接口,则将引用返回给调用者是很干净的。因此,您可以反转依赖关系。你会:
virtual void ExecuteOperation(ICaller* caller)
然后,您可以在实际调用者中实现它(但您在上下文中显然存在并发问题)或在专用类中实现它。你通过这种方式减少耦合,这是一件好事。当然,ICaller会为extra1
和extra2
提供仅针对相关BasicOperation
实现调用的getter。