我有一个抽象类父级,它有多个子级和用于与每个子级交互的空白函数。每个 Child 都会覆盖 Parent 的功能,并以不同的方式与其他 Childs 交互;即 Child1 对 interact_with(Child1)、interact_with(Child2) 等有不同的实现。
在 Parent 中,我有一个函数 interact_with(Parent foo)。每个希望与另一个 Child 交互的 Child 都必须首先通过此功能。到目前为止一切都很好,但是我们遇到了一个问题:在处理了一些基本逻辑之后,Child 需要知道它的参数的具体类型,这样它才能继续调用它自己的重写函数。目前我有这个:
Child1* child1 = dynamic_cast<Child1*>(foo);
Child2* child2 = dynamic_cast<Child2*>(foo);
Child3* child3 = dynamic_cast<Child3*>(foo);
if(child1 != nullptr){
interact_with(child1)
}
else if(child2 != nullptr){
interact_with(child2)
}
else if(child3 != nullptr){
interact_with(child3)
}
它有效,但这不是一个很好的解决方案。当我有这么多类(class)时,情况会变得特别糟糕。这是否表明基础设计有缺陷,如果是,我将如何改进它?
编辑:澄清一下:我有这样的东西
//Parent is an abstract class
class Parent
{
void interact_with(Parent* foo){
//this is here because there is a lengthy code segment
//that needs to be run no matter what child interacts
//with which
//afterwards, I need to interact with whatever foo really is
}
virtual void interact_with(Child1* child){*blank*};
virtual void interact_with(Child2* child){*blank*};
virtual void interact_with(Child3) child){*blank*};
};
class Child1 : public Parent
{
virtual void interact_with(Child1* child){*do something*};
virtual void interact_with(Child2* child){*do something else*};
virtual void interact_with(Child3* child){*do something else*};
};
已经。
最佳答案
使用双重分派(dispatch)的@imreal 答案是正确的。但是,可以使用虚拟成员函数而不是映射和函数指针(这实际上类似于编译器生成的 vtable)来完成分派(dispatch)。
问题是单个虚函数无法解决问题,因为您确实需要双重分派(dispatch)(即关于两个对象的虚调用,而不仅仅是被调用的对象)。
请参阅以下工作示例:
#include <iostream>
class Child1;
class Child2;
class Parent
{
public:
virtual void interact_with(Parent* other) = 0;
virtual void interact_with(Child1* child) {};
virtual void interact_with(Child2* child) {};
};
class Child1 : public Parent
{
public:
virtual void interact_with(Parent* other)
{
other->interact_with(this);
}
virtual void interact_with(Child1* child)
{
std::cout << "Child1 - Child1\n";
}
virtual void interact_with(Child2* child)
{
std::cout << "Child1 - Child2\n";
}
};
class Child2 : public Parent
{
public:
virtual void interact_with(Parent* other)
{
other->interact_with(this);
}
virtual void interact_with(Child1* child)
{
std::cout << "Child2 - Child1\n";
}
virtual void interact_with(Child2* child)
{
std::cout << "Child2 - Child2\n";
}
};
int main()
{
Child1 c1;
Parent* p1 = &c1; // upcast to parent, from p1, we don't know the child type
Child2 c2;
Parent* p2 = &c2;
c1.interact_with(&c2); // single virtual call to Child1 - Child2
p1->interact_with(&c2); // single virtual call to Child1 - Child2
p1->interact_with(p2); // double virtual call to Child2 - Child1 (NB: reversed interaction)
}
输出:
Child1 - Child2
Child1 - Child2
Child2 - Child1
注意最后一个是反的。那是因为要在参数上使用虚函数进行动态分派(dispatch),我必须将 this
指针与参数交换。如果这些相互作用是对称的,这很好。如果不是,那么我建议围绕最通用的包装器创建一个包装器,再次交换 this
和参数。
关于c++ - 使此代码正确多态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28752506/