虚拟函数&x27;s参数未在所有子类中使用;还有更好的设计方法吗? 我写了一些相关C++类,而且我对一个特定继承函数的设计有一些麻烦。

虚拟函数&x27;s参数未在所有子类中使用;还有更好的设计方法吗? 我写了一些相关C++类,而且我对一个特定继承函数的设计有一些麻烦。,c++,oop,inheritance,C++,Oop,Inheritance,具体来说,这些类都是树上的“操作”,我需要能够在树上执行一组任意树操作。我在每个类中都有一个名为ExecuteOperation()的函数 问题是,在某些课程中,我需要比其他课程更多的补充信息。现在,我只需将额外的信息传递给所有类,抽象基类的定义如下: class BasicOperation { public: //... virtual void ExecuteOperation(Tree* tree, multimap<int,Foo*> ex

具体来说,这些类都是树上的“操作”,我需要能够在树上执行一组任意树操作。我在每个类中都有一个名为ExecuteOperation()的函数

问题是,在某些课程中,我需要比其他课程更多的补充信息。现在,我只需将额外的信息传递给所有类,抽象基类的定义如下:

class BasicOperation  {
    public:
    //...
        virtual void ExecuteOperation(Tree* tree, multimap<int,Foo*> extra1, multimap<int,Foo*> extra2) = 0;
    //...
}
Tree* tree;
std::vector<BasicOperation*> operations;
//...
for(size_t i=0;i<operations.size();i++)  {
    operations[i]->ExecuteOperation(tree,extra1,extra2);
}
class基本运算{
公众:
//...
虚拟void执行操作(Tree*Tree,multimap extra1,multimap extra2)=0;
//...
}
BasicOperation子类“SpecialOperation”的后代需要参数extra1和extra2,而“NonspecialOperation”的后代根本不使用这些参数

ExecuteOperation的调用方通常如下所示:

class BasicOperation  {
    public:
    //...
        virtual void ExecuteOperation(Tree* tree, multimap<int,Foo*> extra1, multimap<int,Foo*> extra2) = 0;
    //...
}
Tree* tree;
std::vector<BasicOperation*> operations;
//...
for(size_t i=0;i<operations.size();i++)  {
    operations[i]->ExecuteOperation(tree,extra1,extra2);
}
Tree*Tree;
向量运算;
//...
用于(大小i=0;iExecuteOperation(树,extra 1,extra 2);
}
extra1和extra2的填充取决于特定的树,并且可能需要大量计算(最好不要在每个ExecuteOperation调用中重新创建它们)

有没有更好的方法来设计它,以便只有SpecialOperation对象才能获得传递给它们的参数?或者,将未使用的参数传递给非特殊操作类这样的类通常是好的吗

用两个它不使用的参数定义NonspecialOperation::ExecuteOperation()感觉很奇怪

到目前为止,我唯一想到的是给SpecialLoperation对象返回调用者的指针,并将额外的信息存储在调用者对象中。我不太喜欢这个解决方案,因为extra1和extra2太依赖于当前状态;除了并行化问题,设置只是“感觉”不对

另外,将树、extra1和extra2包装在另一个结构中以传递给ExecuteOperation可能会使它看起来更干净,并且有意义,因为extra1和extra2是树的额外描述符,但我不知道这是否是最好的解决方案:

struct TreeEx  {
    Tree* tree;
    multimap<int,Foo*> extra1, extra2;
};
//in BasicOperation:
virtual void ExecuteOperation(TreeEx* tree_with_info) = 0;
结构树{ 树*树; 多重映射extra1,extra2; }; //在基础计算中: 虚空执行操作(TreeEx*tree_,带_信息)=0;
如果通过接口将引用返回调用方,这是很干净的。因此,您可以反转依赖关系。您将有:

virtualvoid执行操作(ICaller*调用者)

然后,您可以在实际调用方中实现它(但是您的上下文中显然存在并发性问题)或者在专用类中实现它。这样可以减少耦合,这是一件好事。当然,iCaler为
extra1
extra2
提供了getter,这些getter将仅用于相关的
basiccoperation
实现。

使用

虚空执行操作(树*树)

没有额外的理由

通过从
BasicOperation
派生的类中的构造函数传递额外参数。 将允许
basiccoperation
提取所需数据的方法添加到树中

另请参见模式和模式

--编辑--


额外的参数是树特有的

在创建所需命令的基树类中创建一个虚拟函数

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);
 }
并返回所需的命令类,使用构造函数将数据传递到命令中


请参阅模式和模式。

extra1和extra2的填充取决于特定的树;因此,为什么不将它们直接存储在树中,以便SpecialLoperation从树本身提取它们呢?这是一个很好的观点;事实上,这就是我提到TreeEx的原因。树由非常简单的节点对象组成,可以有子节点,例如d依此类推;我必须在根节点周围包装另一个类,如TreeEx,以添加额外的数据。我没有这样做的原因是,只有程序的这一小部分需要连接到树的额外数据,而其余部分只需要节点。额外的参数是树特有的,而操作可以在ot中重用我可以创建一个函数,每次为每个操作提供新的参数,但添加一个循环基本上与检查调用ExecuteOperation()的循环中的类型相同.我不会想到的。为了简单起见,我打算使用类似于TreeEx的东西,但我仍然认为这个答案是有用的。这种复杂的机制对于这个特定的代码来说并没有真正意义,我希望有一个小而优雅的解决方案,但我认为我在这件小事上花费了太多的时间。我会保留所有的在我前进的过程中,我会记住你的答案。谢谢。这很有趣。我会记住这一点;对于这种情况,我想我会继续传递参数(或者像TreeEx一样围绕参数包装一个结构),因为考虑到约束条件,它看起来更简单。