检查传递的类型界面

时间:2014-04-21 09:44:02

标签: c++ oop templates

我有以下界面:

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类型的对象时,这不起作用。这样做的正确方法是什么?

1 个答案:

答案 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。