Re: dynamic_cast<> perfomans
Kai-Uwe Bux wrote:
But if I understand you correctly you're wondering whether every node in
a tree (nodes corresponding to classes) can be assigned a number such
that NumberOf(A) >= NumberOf(B) implies that A is a parent node of B or
equal to B.
And the answer to that is no, because two unrelated nodes would have to
have either equal numbers (incorrectly implying they're the same) or
unequal numbers (incorrectly implying one is a parent node of the
other).
The question is "if no that how"? How it must be implemented (recomended
by C++ standard) to save space and high perfomance?
The standard gives no hints as to how dynamic_cast<> is to be implemented
(there is no recommended implementation); and neither does it give any
guarantees as to performance.
It is important to me -
does C++ garantee the time of dynamic_cast<> in the case of ordinary
inheritance is equal to one-two pseudo expression "if-else"
return (Base*->type_fild >= Derived*->type_fild)? Base*: 0;
or not?
In which way is this information important to you?
1.
The dynamic_cast<> is required by design, because I can not define huge base
class interface but simple interface is not enough to possible derived.
The solution for possible manual replacement of dynamic_cast in the case of
ordinary inheritance came up to my mind, assuming that C++ will do nothing
for perfomance here.
Consider:
Let each derived from first underived base have unique number. But we no
need number, we can use single bit in bitmask
Base->Derived_A1->Derived_B1->Derived_C1->Derived_E1
Base->Derived_A1->Derived_B2->Derived_C2->Derived_E2
[class] [type] [mask]
Base 0x0001 0x0001
Derived_A1 0x0003 0x0002
#
Derived_B1 0x0007 0x0004
Derived_C1 0x000F 0x0008
Derived_E1 0x001F 0x0010
#
Derived_B2 0x0023 0x0020
Derived_C2 0x0063 0x0040
Derived_E2 0x00E3 0x0080
dynamic_cast<>() can be implemented as single if-else operator
//extern Base* ptr;
//int Derived_C1::mask==0x0008;
//dynamic_cast<Derived_C1*>(ptr)
return ( ptr->type & Derived_C1::mask )?
reinterpret_cast<Derived_C1*>(ptr):
0;
The condition is true only if ptr is Derived_C1 or Derived_E1
2.
The 32 bit unsigned can represent 32 distinct class. But fortunatelly, we no
need cast to each derived class, not each class is declaration of uniq
interface.
New interfaces are quite rare declared so 32 bits is enough, but we can use
64 bits and two if-else operators.
All code listed below compiler easy can do itself if programmer could tell
to compiler that class declaration is new interface declaration with the
help of new keyword "interface" and "interface_cast" instead of
dynamic_cast.
Let we have several classes as declarations of base interface extentions in
the inheritance tree. Consider the following example (cut&paste it into
file):
-- cut here --
/*
Base->Derived_A1->Derived_B1->Derived_C1->Derived_E1
ITF0-> NOT_ITF ITF1->
Base->Derived_A1->Derived_B2->Derived_C2->Derived_E2
ITF2->
Base->Derived_A1->Derived_B2->Derived_C3->Derived_E3
ITF2-> NOT_ITF
Derived_C3->Derived_E4
Derived_C3->Derived_E5
Derived_C3->Derived_E6
[class] [type] [mask]
Base 0x0001 0x0001 ITF0
Derived_B1 0x0003 0x0002 ITF1
Derived_B2 0x0005 0x0004 ITF2
*/
#include <stdio.h>
typedef unsigned uint;
//C++ do not support
#define interface
//******************
//ITF0
//******************
class Base interface
{
protected:
static uint type;
public:
virtual uint itype()const {return type;}
enum { _type=0x0001 };
enum { mask=0x0001 };
};
class Derived_A1: public Base {};
//******************
//ITF1
//******************
class Derived_B1 interface: public Derived_A1
{
protected:
static uint type;
public:
uint itype()const {return type;}
enum { _type=0x0003 };
enum { mask=0x0002 };
};
class Derived_C1: public Derived_B1 {};
class Derived_E1: public Derived_C1 {};
//******************
//ITF2
//******************
class Derived_B2 interface: public Derived_A1
{
protected:
static uint type;
public:
uint itype()const {return type;}
enum { _type=0x0005 };
enum { mask=0x0004 };
};
class Derived_C2: public Derived_B2 {};
class Derived_E2: public Derived_C2 {};
class Derived_C3: public Derived_B2 {};
class Derived_E3: public Derived_C3 {};
class Derived_E4: public Derived_C3 {};
class Derived_E5: public Derived_C3 {};
class Derived_E6: public Derived_C3 {};
//******************
//interface_cast
//******************
template<class Tdst,class Tsrc>
Tdst* interface_cast(Tsrc* ptr)
{
fprintf(stderr,"src: %u, dst: %u, &=%u\n", ptr->itype(), Tdst::mask,
(ptr->itype()&Tdst::mask) );
return ( ptr->itype() & Tdst::mask )?
reinterpret_cast<Tdst*>(ptr):
0;
}
//******************
//******************
uint Base::type=Base::_type;
uint Derived_B1::type=Derived_A1::_type;
uint Derived_B2::type=Derived_B2::_type;
Derived_E1 *e1=0;
Derived_E3 *e3=0;
int main()
{
Base *base=new Derived_E2;
printf("%s[%p]\n","Derived_E2",base);
e1=interface_cast<Derived_E1,Base>(base);
printf("%s[%p]->%s[%p]\n","Base",base,"Derived_E1",e1);
e3=interface_cast<Derived_E3,Base>(base);
printf("%s[%p]->%s[%p]\n","Base",base,"Derived_E3",e3);
Base *const tmp=base;
base=interface_cast<Base,Derived_E3>(e3);
printf("%s[%p]->%s[%p]\n","Derived_E3",tmp,"Base",base);
}
-- cut here --
--
Maksim A. Polyanin
"In thi world of fairy tales rolls are liked olso"
/Gnume/