"Peter Koch Larsen" <pk*****@mailme.dk> wrote in message
news:ys********************@news000.worldonline.dk ...
"PKH" <no************@online.no> skrev i en meddelelse
news:FP******************@news4.e.nsc.no...
"steve" <st***@mcube.com.tw> wrote in message
news:ch**********@netnews.hinet.net... >I am writing for game application. Performance is an issue.
>
> Any advise would be appreiciated.
>
I'm using the following approach in a game I'm working on. By inlining
the
RequestClass functions it should be quite fast. (I posted this earlier in
another thread )
[snip]
You answered the question: is it possible to detect the object run time
type
without using dynamic_cast. I see that it is. Could you also demonstrate
that it is faster than dynamic_cast? (In that case you should quote the
compiler and settings used)
/Peter
I hadn't really tested speed, but needed the extra flexibility the ClassID
approach gives.
After doing a test with upcasting from a basepointer which is what I use
most, I was pleasantly suprised.
It's is quite a lot faster in release on the following code.
On an amd 2500+, VC 6.0 for the following code, the results were
In Debug, ClassID 1.03 secs, Dynamic cast 1.34 secs
In Release ClassID 0.13 secs, Dynamic cast 0.81 secs (inline any suitable,
maximize speed)
I checked that EatGrass() was actually called for both loops in release.
Of course the compiler might do some tricks with this code when optimizing,
but I think I can conclude that ClassID is at least as fast as dynamic_cast
(unless there is some mistake in the code).
#include <windows.h>
#include <conio.h>
#include <stdio.h>
typedef char ClassID;
class CClassIDBase
{
public:
static ClassID
m_cClassID;
inline
virtual CClassIDBase* RequestClass(const ClassID& c)
{
return (&c == &m_cClassID) ? this : NULL;
}
};
class CCow : public CClassIDBase
{
public:
static ClassID
m_cClassID;
public:
void EatGrass(){}
inline
virtual CClassIDBase* RequestClass(const ClassID& c)
{
return (&c == &m_cClassID) ? this : CClassIDBase::RequestClass(c);
}
};
class CSuperCow : public CCow
{
public:
static ClassID
m_cClassID;
public:
inline
virtual CClassIDBase* RequestClass(const ClassID& c)
{
return (&c == &m_cClassID) ? this : CCow::RequestClass(c);
}
};
class CBrow : public CClassIDBase
{
public:
static ClassID
m_cClassID;
CCow
m_cCow;
public:
inline
virtual CClassIDBase* RequestClass(const ClassID& c)
{
if (&c == &CCow::m_cClassID)
{
return &m_cCow;
}
else
{
return (&c == &m_cClassID) ? this : CClassIDBase::RequestClass(c);
}
}
};
ClassID
CClassIDBase::m_cClassID = 0,
CCow::m_cClassID = 0,
CSuperCow::m_cClassID = 0,
CBrow::m_cClassID = 0;
int main(int argc, char* argv[])
{
CClassIDBase
*pcBase;
CCow
*pcCow;
CBrow
cBrow;
CSuperCow
cSuperCow;
LARGE_INTEGER
nFreq,
nStartTick,
nEndTick;
BOOL
bRes;
DWORD
i;
float
vFreq,
vClassIDSecs,
vDynamicCastSecs;
bRes = QueryPerformanceFrequency(&nFreq);
vFreq = (float)nFreq.QuadPart;
pcBase = &cSuperCow;
// Class ID
QueryPerformanceCounter(&nStartTick);
for (i = 0; i < 10000000; i++)
{
pcCow = (CCow*)pcBase->RequestClass(CCow::m_cClassID);
if (pcCow)
{
pcCow->EatGrass();
}
}
QueryPerformanceCounter(&nEndTick);
vClassIDSecs = (nEndTick.QuadPart - nStartTick.QuadPart) / vFreq;
// Dynamic_cast
QueryPerformanceCounter(&nStartTick);
for (i = 0; i < 10000000; i++)
{
pcCow = dynamic_cast<CCow*>(pcBase);
if (pcCow)
{
pcCow->EatGrass();
}
}
QueryPerformanceCounter(&nEndTick);
vDynamicCastSecs = (nEndTick.QuadPart - nStartTick.QuadPart) / vFreq;
// You can also do this, which isn't available with dynamic_cast
// since Brow doesn't inherit from cow
if ((pcCow = (CCow*)cBrow.RequestClass(CCow::m_cClassID)) != NULL)
{
pcCow->EatGrass();
}
printf("ClassID: %.2f, DynamicCast: %.2f", vClassIDSecs,
vDynamicCastSecs);
while (!_kbhit());
return 0;
}