在C ++中进行高效的运行时类型检查

时间:2015-01-27 14:00:51

标签: c++ runtime typechecking

我有两个名为' Expression'和' BinExp'如下代码:

class Expression
{
public:
    virtual BinExp* IsBinaryExp() { return NULL; }
};
class BinExp : public Expression
{
public:
    virtual BinExp* IsBinaryExp() { return this; }
};

例如,我的指针变量类型为Expression*,但初始化为new BinExp并作为参数发送到analyse函数,如下代码所示:

int main()
{
    Expression* e = new BinExp;
    analyse(e);
}

analyse函数中,我需要知道e是指向Expression类型还是BinExp类型的指针。在我手中,有三种方法可以做到这一点。

首先:

BinExp* be = e->IsBinaryExp();
if ( be )
{
    printf("Yes, `e` is a binary expression\n");
}

第二

BinExp* be = dynamic_cast<BinExp*>(e);
if ( be )
{
    printf("Yes, `e` is a binary expression\n");
}

第三个:

if ( typeid(*e) == typeid(BinExp) )
{
    BinExp* be = e->IsBinaryExp(); // or dynamic_cast<BinExp*>(e);
    printf("Yes, `e` is a binary expression\n");
}

但是我想知道当我需要在性能是一个问题的循环内频繁执行检查时,哪些方法(或任何其他方法)会更有效率。任何建议,我将不胜感激。

3 个答案:

答案 0 :(得分:2)

最快的方法是保留一个成员变量,比如一个枚举,然后在基类中定义一个内联getter,然后你可以比较结果是否符合预期。

示例(未编译,可能会发生一些错误):

  enum eExpTypes {
        ET_UNDEFINED,
        ET_BINARY
  }
  class Expresion
  {
      protected:
            eExpTypes myType;
      public:
            Expresion(): myType(ET_UNDEFINED){};
            inline eExpTypes getType(){return myType;};
  }

  class BinExpresion : public Expresion
  {
     public:
            BinExpresion():myType(ET_BINARY){};
  }

业绩增长:

  • 你将取出两个指标:从指针到vfptable,从vfptable到函数
  • 如果类型函数是唯一的虚函数
  • ,您的类大小将会减少

动态强制转换通常比你自己的类型检查机制慢,所以如果你的3个例子,第一个应该是最快的。

答案 1 :(得分:0)

最快的将是:

e->printIsBinExp();

在哪里制作要打印或是noop的虚拟方法。

我只是部分开玩笑。 virtual方法的要点是封装不同的类型&#39;处理特定方法 - 不要编写程序只是对不同的运行时类型进行运行时切换。

假设dynamic_cast最快。你会写下:

if (BinExp* be = dynamic_cast<BinExp*>(e)) {
    // ...
}
else if (UnExp* ue = dynamic_cast<UnExp*>(e)) {
    // ...
}
else if (TernExp* te = dynamic_cast<TernExp*>(e)) {
    // ...
}

希望不是。该代码将非常脆弱。你肯定想要设计一个这样的设计:

e->eval();

只做一次virtual电话会议。

答案 2 :(得分:-1)

3号是最优雅的。

为了找出是否哪一个最有效,可以使用一些简单的代码来衡量每个案例的执行时间......

#include <iostream>
#include <chrono>

/*
Case
*/

int main()
{
    const clock_t begin_time = clock();
    // Case
    std::cout << float(clock() - begin_time) / CLOCKS_PER_SEC;

    system("pause");
    return 0;
}