Click to See Complete Forum and Search --> : How to determine object type at run-time?


ctyuang
July 23rd, 2002, 08:47 AM
If my classes defined as follow:



class A
{...};

class B : public A
{...};

class C : public A
{...};




and someone instances an object B from A pointer


A* ap=new B;


Now, how can I instance another object same type as *ap when I get ap pointer? Of course, I dont know whether *ap is an B object or C object.

Maybe I can define an Identify() function in classes to indentify themself, eg:


class B{
public:
vitual int Indentify(void)
{
cout<<"I am B";
return 1;
}
....
};

class C{
public:
vitual int Indentify(void)
{
cout<<"I am C";
return 2;
}
....
};

void main(void)
{
...
A* ap2;
switch(ap->Identify())
{
case 1:
ap2=new B;
break;
case 2:
ap2=new C;
}
}



How can I impliment this without using "switch"?

Thank you

Zeeshan
July 23rd, 2002, 08:56 AM
You can use dynamic_cast to do this. But dont forgot to include at least one virtual function in base class and enable RTTI in VC.

Take a look at this code.


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

class A {
public:
virtual void f() { }
};

class B : public A { };

class C : public A { };

int main()
{
A* pA = new B;

B* pB = dynamic_cast<B*>(pA);

if (pB)
{
cout << "Creating object B" << endl;
pB = new B;
}

delete pA;
delete pB;

return 0;
}


Hope it helps.

ctyuang
July 23rd, 2002, 09:13 AM
Zeehans, thank you for your reply. Your code gives me some inspiration of my design, but it would be quite tedious if I derived many classes from parent class A.

Since "someone" has instances an object from A pointer, and I do not know what is the type of the object instanced from A pointer, it could be B object, C, D, E, F, or even K object.

No matter what object is that, all I wish to do is to instance another same-type object from A pointer. Maybe I can add an identifier as member data of each class, and have a switching in my main().



A* ap2;

switch()
{
case 1:
ap=new B;
break;
case 2:
ap=new C:
break;
...
...
case 10:
ap=new K;
break;
}


This is quite tedious, isnt it?

I wish to have a smater way. Thank you

zdf
July 23rd, 2002, 09:22 AM
I hope I correctly understood the problem:


class B
{
public:
virtual B* New()
{
return new B;
}
};

class D : public B
{
public:
virtual B* New()
{
return new D;
}
};
int main(int argc, char* argv[])
{
B* pb1 = new D;
B* pb2 = pb1->New();

return 0;
}


Regards,

ctyuang
July 23rd, 2002, 09:24 AM
zdf, thank you :D

I am following your idea!

have a ncie day

Graham
July 23rd, 2002, 10:52 AM
Implement a virtual Clone() function:

class A
{
public:
A(const A&);
virtual A* Clone() {return new A(*this);}
};

class B : public A
{
public:
B(const B&);
A* Clone() {return new B(*this);}
};

class C : public A
{
public:
C(const C&);
A* Clone() { return new C(*this);}
};

Of course, you could use the default constructor, rather than the copy, but you should get the idea.

NB: ANSI C++ would allow you to change the return type of each Clone function to pointer-to-enclosing class (i.e. B* B::Clone() and C* C::Clone() ), but VC++ won't allow that.

Graham
July 23rd, 2002, 10:53 AM
Apologies: I missed zdf's answer before adding mine.