只有当你的类有一个虚拟表时,RTTI才能工作。如果你有一个虚拟表,你可以实现虚拟函数。您应该在对象类型的开关上使用虚函数的原因是,它与继承链一起工作得更好,并且在添加新类时不那么脆弱。

例如:

代码语言:javascript复制class A : public V {}

class B : public V{}

void do_something( const V & v )

{

if (typeid(A) == typeid(v)) { .. its an A .. }

if (typeid(B) == typeid(v)) { .. its a B .. }

}

int main()

{

do_something( A() );

do_something( B() );

}现在,如果我们添加一个也是从V派生的新类C并调用do_something( C() ) (而不更改do_something的实现),则不会发生任何事情。(编译时没有错误)。如果我们添加一个从A派生的类D,也不会出错,也不会发生任何事情。

将这与虚函数的行为进行对比

代码语言:javascript复制struct V

{

virtual void do_something() const =0;

};

struct A

{

virtual void do_something() const { ... its an A ... }

}

struct B

{

virtual void do_somethine() const { ... its a B ... }

}

void do_something( const V & v )

{

v.do_something();

}现在,如果我们从V派生C,并且没有实现C::do_something(),我们将得到一个编译时错误。如果我们从A派生D,并且不实现D::do_something(),我们将得到对A::do_something()的调用。

因此,这是虚拟函数比RTTI更受青睐的主要原因。但是,有时您可能会觉得do_something的行为不属于您的V或A B C类。因此,您可能会使用RTTI (通过typeid或dynamic_cast)。更好的解决方案通常是实现类层次结构的访问者模式。