c++ - 使此代码正确多态

标签 c++ class polymorphism dynamic-cast

我有一个抽象类父级,它有多个子级和用于与每个子级交互的空白函数。每个 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/

相关文章:

java - 为什么编译器显示错误

c++ - 虚拟类和多态性

java - 为什么不能降低 Java 子类中方法的可见性?

c++ - C 中的 typedef 函数用法

c++ - 另一个线程的调试实例改变了我的数据

java - 这两个java数据结构有什么区别?

java - 单点对象和数组的解决方法

c++ - c++14中std::string的运算符后缀

c++ - 如何避免 VS 中 unique_ptr 检查的性能警告?

python - 区间类 - Python