Sign in to follow this  
Grahf750

find object's class name

Recommended Posts

Is there a way to find an object's class? I have a method that will work a little differently for two different objects but I would like to keep it as one method. I could put a variable in each object to tell what it is, but if it is possible to determine what an object's class is then I can use that and I will have 2 less variables :)

Share this post


Link to post
Share on other sites
Yes there is a way (I suppose you use c++), its called RTTI

and it looks like:


struct A{};
struct X : public A {};
struct Y : public A {};

void handle_X( X& b )
{
//do some stuff
}

void handle_Y( Y& b )
{
//do some stuff
}

void test( A& b )
{
if( typeid( b ) == typeid( X ) )
handle_X( dynamic_cast< X >( b ) );
if( typeid( b ) == typeid( Y ) )
handle_Y( dynamic_cast< Y >( b ) );
}

Share this post


Link to post
Share on other sites
Expanding on what ext has said, take a look at this link if you want to get the name of the class as well :


#include <iostream>
#include <typeinfo>
using namespace std;

struct A { virtual ~A() { } };
struct B : A { };

struct C { };
struct D : C { };

int main() {
B bobj;
A* ap = &bobj;
A& ar = bobj;
cout << "ap: " << typeid(*ap).name() << endl;
cout << "ar: " << typeid(ar).name() << endl;

D dobj;
C* cp = &dobj;
C& cr = dobj;
cout << "cp: " << typeid(*cp).name() << endl;
cout << "cr: " << typeid(cr).name() << endl;
}


Share this post


Link to post
Share on other sites
At least for my setup, the "human readable" name was barely that, and looked a lot more like the class name given during linker errors. Depending on what exactly you want to do, simple inheritance or template use will provide a more robust solution.

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
At least for my setup, the "human readable" name was barely that, and looked a lot more like the class name given during linker errors.


It depends on your compiler. I seem to remember that VC++ does return actually readable type names. GCC's (and, I guess ICC's) need to be passed to ::abi::__cxa_demangle()

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
Quote:
Original post by Telastyn
At least for my setup, the "human readable" name was barely that, and looked a lot more like the class name given during linker errors.


It depends on your compiler. I seem to remember that VC++ does return actually readable type names. GCC's (and, I guess ICC's) need to be passed to ::abi::__cxa_demangle()


Indeed. VC7 prefix class names with the string "class", which is somewhat stupid.

About what ext wrote: VC7 (2003) do not work very well when you try to play with typeid(). For example:

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

void foo(A& a)
{
std::cout << typeid(a).name() << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;

foo(a);
foo(b);

return 0;
}


It won't print

A
B

but

A
A


Regards,

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
About what ext wrote: VC7 (2003) do not work very well when you try to play with typeid(). For example:

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


Your types aren't polymorphic so VC7's behaviour is absolutely correct. Add a virtual function (e.g. the destructor) to A and it'll work as you seem to expect.

Share this post


Link to post
Share on other sites
I wrote similar code as to what Emmanuel posted, then added a virtual function to A, and the program crashes.

#include <iostream>

class A
{
public:
A() { }

virtual void bar() {};
};

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

void foo(A &a)
{
std::cout << typeid(a).name() << std::endl;
}

int main()
{
A a;
B b;

foo(a);
foo(b);

getchar();

return 0;

}



I get this error message:

Unhandled exception at 0x7c81eb33 in test.exe: Microsoft C++ exception: __non_rtti_object @ 0x0012fccc.


Non RTTI object? What is meant by this? I get the same error when using a pointer instead of reference also.
If i comment out the virtual function, it work but print out A A instead of A B, as Fruny explained why...

Share this post


Link to post
Share on other sites
You need to enable RTTI in your project settings when compiling - by default, that information isn't included in the compiled app, in keeping with the C++ philosophy of "you don't pay for (or get) what you don't explicitly ask for".

Meanwhile: consider that this sort of thing can *usually* be avoided. There are lots of solutions for the problem as posed:

Quote:
I have a method that will work a little differently for two different objects but I would like to keep it as one method.


The best option depends on exactly how it will differ, but consider something like this:


#include <iostream>
using namespace std;

class A {
virtual void different() {
cout << "this is the part that's different" << endl;
}
void common() {
cout << "this part is common to all classes" << endl;
}
public:
virtual ~A() { cout << "Cleaning up an A" << endl; }
A* doSomething() { common(); different(); common(); return this; }
};

class B: public A {
// implement the different part here as an override
void different() {
cout << "tnereffid s'taht trap eht si siht" << endl;
}
public:
~B() { cout << "Cleaning up a B" << endl; }
};

int main() {
delete (new A())->doSomething();
cout << "And now for something completely, er, slightly different:" << endl;
delete (new B())->doSomething();
}



(Note that the A dtor is invoked implicitly from the B destructor, because the bases and members of an object must be cleaned up as well as the object itself.)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this