Я написал простой пример, который оценивает среднее время вызова виртуальной функции, используя интерфейс базового класса и dynamic_cast и вызов не виртуальной функции. Вот он:
#include <iostream>
#include <numeric>
#include <list>
#include <time.h>
#define CALL_COUNTER (3000)
__forceinline int someFunction()
{
return 5;
}
struct Base
{
virtual int virtualCall() = 0;
virtual ~Base(){};
};
struct Derived : public Base
{
Derived(){};
virtual ~Derived(){};
virtual int virtualCall(){ return someFunction(); };
int notVirtualCall(){ return someFunction(); };
};
struct Derived2 : public Base
{
Derived2(){};
virtual ~Derived2(){};
virtual int virtualCall(){ return someFunction(); };
int notVirtualCall(){ return someFunction(); };
};
typedef std::list<double> Timings;
Base* createObject(int i)
{
if(i % 2 > 0)
return new Derived();
else
return new Derived2();
}
void callDynamiccast(Timings& stat)
{
for(unsigned i = 0; i < CALL_COUNTER; ++i)
{
Base* ptr = createObject(i);
clock_t startTime = clock();
for(int j = 0; j < CALL_COUNTER; ++j)
{
Derived* x = (dynamic_cast<Derived*>(ptr));
if(x) x->notVirtualCall();
}
clock_t endTime = clock();
double callTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;
stat.push_back(callTime);
delete ptr;
}
}
void callVirtual(Timings& stat)
{
for(unsigned i = 0; i < CALL_COUNTER; ++i)
{
Base* ptr = createObject(i);
clock_t startTime = clock();
for(int j = 0; j < CALL_COUNTER; ++j)
ptr->virtualCall();
clock_t endTime = clock();
double callTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;
stat.push_back(callTime);
delete ptr;
}
}
int main()
{
double averageTime = 0;
Timings timings;
timings.clear();
callDynamiccast(timings);
averageTime = (double) std::accumulate<Timings::iterator, double>(timings.begin(), timings.end(), 0);
averageTime /= timings.size();
std::cout << "time for callDynamiccast: " << averageTime << std::endl;
timings.clear();
callVirtual(timings);
averageTime = (double) std::accumulate<Timings::iterator, double>(timings.begin(), timings.end(), 0);
averageTime /= timings.size();
std::cout << "time for callVirtual: " << averageTime << std::endl;
return 0;
}
Похоже, callDynamiccast занимает почти в два раза больше времени.
время для callDynamiccast: 0,000240333
время для callVirtual: 0,0001401
Любые идеи, почему это происходит?
EDITED: создание объекта теперь производится в отдельной функции, поэтому комплер не знает его реального типа. Почти тот же результат.
EDITED2: создайте два разных типа производных объектов.