繁体   English   中英

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

[英]Efficient run-time type checking in C++

我有两个名为“ 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");
}

但是我想知道当我需要在涉及性能的循环中频繁执行检查时,哪种方式(或其他方式)会更有效。 任何建议,我将不胜感激。

最快的方法是保留一个成员变量(例如enum),然后在基类中定义一个内联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个示例,第一个应该是最快的。

最快的将是:

e->printIsBinExp();

在其中创建可打印或不使用虚拟方法的位置。

我只是在开玩笑。 virtual方法的重点是封装不同类型对特定方法的处理-而不是编写程序只是对不同的运行时类型进行运行时切换。

假设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呼叫就可以做正确的事情。

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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM