[英]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){};
}
性能提升:
动态转换通常比建立自己的类型检查机制要慢,因此对于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.