如何从 parent 投射到 chlid class 的接口

How to cast from parent to interface of chlid class

假设我有一个 parent class Parent 和 child classes Child1Child2 有后者实施 MyInterface:

class Parent {
    public:
        Parent();
        virtual ~Parent();
        virtual void MyMethod();
}
class MyInterface {
    public:
        virtual ~MyInterface() {}
        virtual void MyInterfaceMethod() = 0;
}
class Child1 : public Parent {
    public:
        Child1();
        virtual ~Child1();
}
class Child2 : public Parent, MyInterface {
    public:
        Child2();
        virtual ~Child2();
        virtual void MyInterfaceMethod() override;
}

然后说我得到了一个 Parent* 指针,我想检查 object 是否正在实现 MyInterface,如果是,则将其转换为 MyInterface* .

我试过这样实现:

void MyFunction(Parent* p) {
    MyInterface* i = dynamic_cast<MyInterface*>(p);
    if (i != 0)
        DoSomething();
    else
        cout << "Cannot do anything.";
}

但 i 始终等于 0,表示它永远不会转换为 MyInterface* 类型,即使我确定 object 具有良好的类型。

我该如何实现?

您的 classes 必须是 多态类型 才能 dynamic_cast 工作。

实现此目的的最简单方法是添加

virtual ~Parent() = default;

Parent class 的 public 区域。然后 dynamic_cast 会像松露猪一样在继承树周围嗅探你的界面。

Child2 private继承自MyInterface,除非MyFunction()有权限访问private基础子对象,dynamic_cast将永远失败。

因为 MyInterface 似乎是一个 接口 ,我想你想要 public 继承。

class Child2 : public Parent, public MyInterface { }
//                            ~~~~~~      

LIVE(修复了其他错误)

或者,我们可以使用 Visitor Pattern:

而不是 dynamic_cast
#include <iostream>

class MyInterface {
public:
    virtual void DoSomething() = 0;
};

class Parent {
public:
    virtual ~Parent() = default;
    virtual void accept(class Visitor& visitor) = 0;
};

class Child1 : public Parent {
public:
    virtual void accept(Visitor& visitor);
};

class Child2 : public Parent, public MyInterface {
public:
    virtual void accept(Visitor& visitor);
    virtual void DoSomething();
};

class Visitor
{
public:
    void visit(Child1& child);
    void visit(Child2& child);
};

void Child1::accept(Visitor& visitor) { visitor.visit(*this); }
void Child2::accept(Visitor& visitor) { visitor.visit(*this); }
void Child2::DoSomething() { std::cout << "Do something.\n"; }

void Visitor::visit(Child1& child) { std::cout << "Cannot do anything.\n"; }
void Visitor::visit(Child2& child) { child.DoSomething(); }

void MyFunction(Parent& p) {
    Visitor v;
    p.accept(v);
}

int main()
{
    Child1 c1;
    Child2 c2;
    MyFunction(c1);
    MyFunction(c2);
}

输出:

Cannot do anything.

Do something.