使用dynamic_cast进行运行时类型识别

时间:2013-02-09 02:35:44

标签: c++ dynamic-cast static-cast

在阅读Essential c ++第5.10章运行时类型识别时,我遇到了一个问题。先介绍一下背景知识。有一个名为num_sequence的基类和一个来自Fibonacci的类num_sequence。在基类中,有一个名为gen_elems的虚函数,派生类有自己的定义。

以下内容来自本书。

Fibonacci fib;
num_sequence *ps = &fib;
ps->gen_elems(64);
  

我们知道将调用gen_elems()的Fibonacci实例。   然而,虽然我们从这个测试中知道ps解决了Fibonacci   class对象,试图调用Fibonacci实例   gen_elems()直接通过ps导致编译时错误:

     

PS->斐波那契:: gen_elems(64); //给出编译时错误

     

ps不知道它所解决的对象的类型,即使我们和typeid和虚函数机制也是如此。

     

要调用gen_elems()的Fibonacci实例,我们必须指示编译器将ps转换为Fibonacci类型的指针。 static_cast和dynamic_cast都可以完成这项工作。< / p>

我对这句大胆的句子感到困惑。 ps->gen_elems(64)实际上调用了gen_elems()的Fibonacci实例。为什么需要我们使用static_cast和dynamic_cast将其转换为Fibonacci类型的指针?

1 个答案:

答案 0 :(得分:4)

大多数情况下,您只需正常调用虚方法,让多态执行其工作,根据需要调用派生最多的实现。作者试图解释的是,也可以在不经过多态的情况下直接调用虚拟方法的特定实现。

假设某个类派生自Fibonacci以再次覆盖gen_elems(),但您不想调用该覆盖,而是要调用Fibonacci覆盖。通过在编译时将num_sequence指针转换为Fibonacci指针(或后代指针),它允许编译器访问Fiboncci vtable,以便它可以发出代码直接调用{{ 1}}(如果在运行时指向的对象实际上不是Fibonacci::gen_elems()或后代的实例,则可能会崩溃/损坏您的应用程序。这在编译时无法验证。)

例如:

Fibanocci

class num_sequence
{
public:
    virtual void gen_elems(int value)
    {
        std::cout << "num_sequence" << std::endl;
    }
};

class Fibonacci : public num_sequence
{
public:
  void gen_elems(int value)
  {
        std::cout << "Fibonacci" << std::endl;
  }
};

class SomethingElse : public Fibonacci
{
public:
  void gen_elems(int value)
  {
        std::cout << "SomethingElse" << std::endl;
  }
};