我有以下界面:
struct Base {};
struct Renderable {};
struct Updateable {};
类使用它:
class Foo1 : Base {};
class Foo2 : Base, Renderable {};
class Foo3 : Base, Renderable, Updateable {};
有一个函数接受这些类型的对象:
template <typename T>
void add(T* obj)
{
// Object inherits Renderable interface
if (static_cast<Renderable*>(obj))
...
// Object inherits Updateable interface
if (static_cast<Updateable*>(obj))
...
}
当我传递Foo1
类型的对象时,这不起作用。这样做的正确方法是什么?
答案 0 :(得分:3)
static_cast<T>()
不检查运行时类型信息; dynamic_cast<T>()
。如果编译器默认关闭代码,则需要在编译代码时将static_cast
替换为dynamic_cast
并启用运行时类型信息(RTTI)。您需要确保Base
至少有一个虚函数。
请注意,通常这不是一个非常健壮的设计,因为当您向层次结构添加其他类型时,add()
函数可能会中断。更好的方法是在Base
中实施visitor pattern以及执行add
的代码。
以下是如何做到这一点:
struct Visitor {
virtual void visitFoo1(Foo1 &foo1);
virtual void visitFoo2(Foo2 &foo2);
virtual void visitFoo3(Foo3 &foo3);
};
struct Base {
virtual void accept(visitor& v);
...
};
struct Foo1 : public Base {
virtual void accept(visitor& v) {
visitFoo1(*this);
}
...
};
struct Foo2 : public Base {
virtual void accept(visitor& v) {
visitFoo2(*this);
}
...
};
struct Foo3 : public Base {
virtual void accept(visitor& v) {
visitFoo3(*this);
}
...
};
现在具有add
功能的代码可以执行此操作:
struct FooProcessor : public visitor {
virtual void visitFoo1(Foo1 &foo1) {
...
}
virtual void visitFoo2(Foo2 &foo2) {
...
}
virtual void visitFoo3(Foo3 &foo3) {
...
}
void add(Base &b) {
b.accept(*this);
}
}
当您在accept
的实例上致电Base
时,它会回拨其中一个visitFooN
个功能,从而无需使用RTTI。