我想放弃虚函数来支持函数指针,所以我做了一些分析,这是怎么做的。
我要做的是决定是否使用虚函数或函数指针(int(* fcnPtr)(int);)来实现多态。
运行时多态性1:
运行时多态性2(我觉得有点快,但设计不好):
这将导致两个调用,一个用于直接方法,然后是函数指针,将在每个子类中重新定义。 即使有两个调用,它仍然比虚拟函数快(120毫秒),对于10 * 1000 * 1000调用,对于1000个子类,我认为这是由于虚函数查找,如果我没有弄错,它在这种情况下,我必须在1000个类之间查找正确的类来调用正确的函数。
我创建了一个基类
void testFct()
{
int c = 0; c+=10;
}
class Base_Class{
public:Base_Class(){}
~Base_Class(){}
virtual void v_Fct() __attribute__ ((noinline)){ int c = 0; c+=10;
void fct() __attribute__ ((noinline)){ fcnPtr(); }
void (*fcnPtr)() = testFct;
};
然后我生成了1000个这样的子类。
class Child_Class_0: public Base_Class
{
public:
Child_Class_0(){}
virtual void v_Fct() __attribute__ ((noinline)){ int c = 0; c+=10;}
};
class Child_Class_1: public Base_Class
{
public:
Child_Class_1(){}
virtual void v_Fct() __attribute__ ((noinline)){ int c = 0; c+=10;}
};
我还生成了这样的工厂函数,以便在运行时创建对象:
Base_Class *createObj( int i )
{
switch ( i ) {
case 0:
return new Child_Class_0();
break;
case 1:
return new Child_Class_1();
break;
case ..:
case 999:
}
以下是分析功能:
void profileVirtuals( int classCount , qreal maxCalls )
{
qreal i = 0;
QElapsedTimer myTimer;
myTimer.start();
/// At this point , the compiler has no idea
/// which child class to instantiate
for ( ;i < maxCalls; ++i) {
int randChild = random( 0 , classCount );
Base_Class *cc = createObj( randChild );
if( cc ){
/// Call virtual function
cc->v_Fct();
delete cc;
}
/// Make sure we are not missing any calls
else
qDebug() << "NULL";
}
int elapsed = myTimer.elapsed();
qDebug() << "VIRTUAL Function Called : " << i << " times.";
qDebug() << "DONE : " << elapsed;
}
void profileDirects( int classCount , qreal maxCalls )
{
qreal i = 0;
QElapsedTimer myTimer;
myTimer.start();
/// At this point , the compiler has no idea
/// which child class to instantiate
for ( ;i < maxCalls; ++i) {
int randChild = random( 0 , classCount );
Base_Class *cc = createObj( randChild );
if( cc ){
/// Call direct function
cc->fct();
delete cc;
}
/// Make sure we are not missing any calls
else
qDebug() << "NULL";
}
int elapsed = myTimer.elapsed();
qDebug() << "DIRECT Function Called : " << i << " times.";
qDebug() << "DONE : " << elapsed;
}
以下是主要功能,我将虚拟功能和直接功能分别称为10 * 1000 * 1000次
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int classCount = 1000;
qreal maxCalls = 10 * 1000 * 1000;
profileVirtuals( classCount , maxCalls );
profileDirects( classCount , maxCalls );
return a.exec();
}
我得到的是10 * 1000 * 1000的电话,大约120毫秒的差异(当然直接电话更快)。毕竟没有那么显着的差异
代码在Qt框架中,但可以很容易地理解为标准C ++。 如果有什么不清楚的地方,关于我刚刚做了什么,或者试图做什么,我会更新问题。
结论:
如果100个子类中的子类较少,则多态性1比多态性2快。
多态性2比多态性1快,如果有很多子类,超过1000个子类,则vTable查找会降低它的速度。