Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Comparing if two objects are of same type without RTTI

Reply
Thread Tools

Comparing if two objects are of same type without RTTI

 
 
vj
Guest
Posts: n/a
 
      04-20-2011
Hi All,

Just realized that one can directly compare the vptr of two objects to
check if they belong to the same class or not. Below is the example
code:

<code>
#define VPTR(__X__) (*((int*)&(__X__)))

class A{
public:
virtual ~A(){}
};
class B{
public:
virtual ~B(){}
};

int main(){
A a1,a2;
B b1;
ASSERT( VPTR(a1)==VPTR(a2) );
ASSERT( VPTR(a1)!=VPTR(b) );
}
</code>

This makes it possible to check if two objects are of same type or not
even if RTTI support is not available (like we have on some embedded
platforms). I do understand that this method is only applicable if the
said classes have a vtable. But I am not sure if there are any other
gotchas' that I am overlooking. Whats your take on this.

Thanks,
~Vaibhav

 
Reply With Quote
 
 
 
 
SG
Guest
Posts: n/a
 
      04-20-2011
On 20 Apr., 12:48, vj wrote:
>
> Just realized that one can directly compare the vptr of two objects


The what? The C++ ISO standard does not say anything about a "vptr".
(And no, I don't want you to explain to me how virtual functions are
typically implemented.)

> [ ... horrible non-portable hack ... ]
>
> This makes it possible to check if two objects are of same type or not
> even if RTTI support is not available (like we have on some embedded
> platforms). I do understand that this method is only applicable if the
> said classes have a vtable. But I am not sure if there are any other
> gotchas' that I am overlooking. Whats your take on this.


I think I answered that already by summarizing your code with
"horrible non-portable hack". I don't know what I would do in your
position. I guess I would first question the design that required me
to use typeid. If the design is ok (which is hard to tell without any
more details) I'd consider filing a complaint with the compiler vendor
about the lack of RTTI.

SG
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      04-20-2011
On 4/20/2011 6:48 AM, vj wrote:
> Just realized that one can directly compare the vptr of two objects to
> check if they belong to the same class or not.


That requires that there *is* such a thing as 'vptr' in both objects.

> Below is the example
> code:
>
> <code>
> #define VPTR(__X__) (*((int*)&(__X__)))


BTW, the use of double underscores in a name is reserved by the
implementation (even if it's a name of a formal argument of a macro).
There is *really* no need for those double underscores here.

>
> class A{
> public:
> virtual ~A(){}
> };
> class B{
> public:
> virtual ~B(){}
> };


What's going to happen if

class C {
A a; // contained
};

and you compare a 'C' to an 'A'?

>
> int main(){
> A a1,a2;
> B b1;
> ASSERT( VPTR(a1)==VPTR(a2) );
> ASSERT( VPTR(a1)!=VPTR(b) );
> }
> </code>
>
> This makes it possible to check if two objects are of same type or not
> even if RTTI support is not available (like we have on some embedded
> platforms). I do understand that this method is only applicable if the
> said classes have a vtable. But I am not sure if there are any other
> gotchas' that I am overlooking. Whats your take on this.


See above.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
gwowen
Guest
Posts: n/a
 
      04-20-2011
On Apr 20, 1:08*pm, Victor Bazarov <(E-Mail Removed)> wrote:
> On 4/20/2011 6:48 AM, vj wrote:
>
> > Just realized that one can directly compare the vptr of two objects to
> > check if they belong to the same class or not.

>
> That requires that there *is* such a thing as 'vptr' in both objects.
>
> *> Below is the example
>
> > code:

>
> > <code>
> > #define VPTR(__X__) * (*((int*)&(__X__)))

>
> BTW, the use of double underscores in a name is reserved by the
> implementation (even if it's a name of a formal argument of a macro).
> There is *really* no need for those double underscores here.
>
>
>
> > class A{
> > public:
> > * * *virtual ~A(){}
> > };
> > class B{
> > public:
> > * * *virtual ~B(){}
> > };

>
> What's going to happen if
>
> * * class C {
> * * * *A a; // contained
> * * };
>
> and you compare a 'C' to an 'A'?


Or if sizeof(int)!= sizeof(_vptr)

(obviously, presupposing the usual implementation)
 
Reply With Quote
 
gwowen
Guest
Posts: n/a
 
      04-20-2011
On Apr 20, 1:31*pm, gwowen <(E-Mail Removed)> wrote:

> Or if sizeof(int)!= sizeof(_vptr)
>
> (obviously, presupposing the usual implementation)


class foo {
public:
int x;
virtual void reset() {x=0;};
virtual void increment() { x += 1;} ;
}

class tagged_foo : public foo
{
public:
std::string tag;
}

Given the "as is" rule, I can't see any reason why, on an
implementation lacking RTTI, that the vptr for tagged_foo should be
different for foo, since I don't override any of the virtual
functions.

So even as a non-standard, implementation-specific hack, the compiler
may decide to undermine you, in the name of efficiency.
 
Reply With Quote
 
vj
Guest
Posts: n/a
 
      04-20-2011
Thanks for the reply,

@SG
>I guess I would first question the design that required me
>to use typeid. If the design is ok (which is hard to tell without any
>more details) I'd consider filing a complaint with the compiler vendor
>about the lack of RTTI.


This is simply a test code. There is nothing production about it. I
simply wanted to test an idea thats all.

@ Victor Bazarov
>BTW, the use of double underscores in a name is reserved by the
>implementation (even if it's a name of a formal argument of a macro).
>There is *really* no need for those double underscores here.


Please bear with the use of __X__ I wasnt aware that the use of
double underscore was reserved even for formal arguments of a macro.
Thanks for pointing this out.


@gwowen
>Or if sizeof(int)!= sizeof(_vptr)


Yes you are right. But if this code is specifically for some platform
where sizeof(int) == sizeof(_vptr) (like IA32) then i guess this hack
is workable, though there is nothing portable about it.


>What's going to happen if
> class C {
> A a; // contained
> };
>and you compare a 'C' to an 'A'?


>class tagged_foo : public foo
>{
>public:
> std::string tag;
>}

This two really kills the generic use of this hack. Thanks for
pointing this out. I am more upset for the first one which definitely
will give false positives. Though I still think that this hack can be
used on classes residing on the same level of a class hierarchy and
its known that they don't have any associations with each other.

Thanks for your comments guys,
~Vaibhav
 
Reply With Quote
 
gwowen
Guest
Posts: n/a
 
      04-20-2011
On Apr 20, 1:46*pm, gwowen <(E-Mail Removed)> wrote:

> class tagged_foo : public foo
> {
> public:
> * std::string tag;
>
> }
>
> Given the "as is" rule, I can't see any reason why, on an
> implementation lacking RTTI, that the vptr for tagged_foo should be
> different for foo, since I don't override any of the virtual
> functions.


OK, the destructor... but replace std::string with a POD type that
doesn't need destructificating, and I think the point still holds.
 
Reply With Quote
 
vj
Guest
Posts: n/a
 
      04-20-2011
On Apr 20, 6:44*pm, gwowen <(E-Mail Removed)> wrote:
> On Apr 20, 1:46*pm, gwowen <(E-Mail Removed)> wrote:
>
> > class tagged_foo : public foo
> > {
> > public:
> > * std::string tag;

>
> > }

>
> > Given the "as is" rule, I can't see any reason why, on an
> > implementation lacking RTTI, that the vptr for tagged_foo should be
> > different for foo, since I don't override any of the virtual
> > functions.

>
> OK, the destructor... but replace std::string with a POD type that
> doesn't need destructificating, and I think the point still holds.


I tried this definition

class Cublic A{
int j;
};

And it seems that MS C/C++ v14.0 compiler still allocates a different
vtable for class C , even though it could have reused the existing
vtable from class A. This was done with maximum optimizations on (/
Ox). I havent tried GCC though but seems like this hack works atleast
on MSVC .

~Vaibhav
 
Reply With Quote
 
Thomas J. Gritzan
Guest
Posts: n/a
 
      04-20-2011
Am 20.04.2011 15:52, schrieb vj:
> On Apr 20, 6:44 pm, gwowen<(E-Mail Removed)> wrote:
>> On Apr 20, 1:46 pm, gwowen<(E-Mail Removed)> wrote:
>>
>>> class tagged_foo : public foo
>>> {
>>> public:
>>> std::string tag;

>>
>>> }

>>
>>> Given the "as is" rule, I can't see any reason why, on an
>>> implementation lacking RTTI, that the vptr for tagged_foo should be
>>> different for foo, since I don't override any of the virtual
>>> functions.

>>
>> OK, the destructor... but replace std::string with a POD type that
>> doesn't need destructificating, and I think the point still holds.

>
> I tried this definition
>
> class Cublic A{
> int j;
> };
>
> And it seems that MS C/C++ v14.0 compiler still allocates a different
> vtable for class C , even though it could have reused the existing
> vtable from class A. This was done with maximum optimizations on (/
> Ox). I havent tried GCC though but seems like this hack works atleast
> on MSVC .


MSVC can't reuse the vtables for this, because the vtable also contains
the RTTI pointer. If you have a compiler without (or with disabled) RTTI
support, the vtables could be merged, because no virtual function in
class A has changed in class C.

You should test if this hack really works with your target compiler on
your target platform; but I advise not to use it in production code.

Instead, you should use virtual functions (think Visitor Pattern) or
integer IDs (or enums) per class.

--
Thomas
 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      04-20-2011
On 4/20/2011 5:08 AM, Victor Bazarov wrote:
> On 4/20/2011 6:48 AM, vj wrote:
>> Just realized that one can directly compare the vptr of two objects to
>> check if they belong to the same class or not.

>
> That requires that there *is* such a thing as 'vptr' in both objects.
>
> > Below is the example
>> code:
>>
>> <code>
>> #define VPTR(__X__) (*((int*)&(__X__)))


> What's going to happen if
>
> class C {
> A a; // contained
> };
>
> and you compare a 'C' to an 'A'?


I think multiple inheritance would toss it off too.


--
http://crazycpp.wordpress.com
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Create objects that contains objects of the same type mike Java 1 03-03-2009 04:20 PM
How to judge if two objects have the same type? shuisheng C++ 15 12-02-2006 07:13 AM
typeid behavior on object without RTTI Derek C++ 4 03-23-2005 09:56 PM
float/double equality in template definition without rtti Alexander Block C++ 26 05-29-2004 02:37 PM
RTTI versus a base class enum to represent type BillyO C++ 2 09-30-2003 10:21 PM



Advertisments