如何从 parent 投射到 chlid class 的接口
How to cast from parent to interface of chlid class
假设我有一个 parent class Parent
和 child classes Child1
和 Child2
有后者实施 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.
假设我有一个 parent class Parent
和 child classes Child1
和 Child2
有后者实施 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.