Getting class type

J

Jon Slaughter

Is there any way to get the class type from a pointer?

I'm working on a class that acts as a set:

I have two classes, one called FSet and the other called Element.

FSet inherets Element and has an internal pointer to a list of pointer of
Element type.


I have method in FSet that adds an Element to the list(does memory
management and checks if its already there).


So, I might I can do something like this:

FSet S;
FSet S1;
SomeClass C;
Element A, B, C;

S.Add(A);
S.Add(B);
S.Add(C);
S.Add((Element)S);
S.Add((Element)C);


Now, I would like to write a method that lets me get an element from the
list, but I would also need to know what class type it is.

i.e. I would need something like:

void *C = S.Get(3);

if (ClassType(C) == 'FSet')
{
..........
}
if (ClassType(C) == 'Element')
{
........
}
if (ClassType(C) == 'etc')
{
........
}


I'm not sure if its possible to do this or not ;/ (I'm sure its possible,
but not sure if C++ keeps track of class types and there instantiation(I
doubt it does)).


If what I'm trying to do is not possible the way I am doing it, is there
another way? I want to create a class that represents a set of "arbitrary
elements"(i.e. any class type, not just of one type).

Thanks
Jon
 
E

eddy_ruslim

try rtti
wicked name!
if u try to make somekind of compiler it is not that simple! But what
is in life?
Edernity
---------
if it help
please help me provide better school supplies for childrenof indonesia.
it may be a donation but I merely ask you to letme send email to you
from one of the product of I'm affiliated and please register there on
mechant account free. If you even want you refund back on your dollar
of i-kard, its ok, I'll send you just use regular delivery on shipping
please. Please note this is very safe since this is a bonafid company.
remember your credit card company will confirm you on your purchase.
Still have doubts, sign on a personal account and let me contact you
again on it. just one mail pls
also
I'm also affiliated to this site:
www.getaportal.com/portals/edd y_ruslim
 
R

Rolf Magnus

Jon said:
Is there any way to get the class type from a pointer?

I'm working on a class that acts as a set:

I have two classes, one called FSet and the other called Element.

FSet inherets Element and has an internal pointer to a list of pointer of
Element type.

I don't see any pointer in your example.
I have method in FSet that adds an Element to the list(does memory
management and checks if its already there).


So, I might I can do something like this:

FSet S;
FSet S1;
SomeClass C;
Element A, B, C;

S.Add(A);
S.Add(B);
S.Add(C);
S.Add((Element)S);

Don't use C style casts. Generally, you should need a cast only rarely, and
then, use the appropriate C++ cast (dynamic_cast, static_cast, const_cast
or reinterpret_cast).
Also, this will probably not do what you want. It will create a new object
of class Element and copy only the Element part of S into that object. This
is called slicing.
S.Add((Element)C);


Now, I would like to write a method that lets me get an element from the
list, but I would also need to know what class type it is.

It is Element, since you stored only objects of that type in your container.
i.e. I would need something like:

void *C = S.Get(3);

Don't use pointers to void.
if (ClassType(C) == 'FSet')
{
.........
}
if (ClassType(C) == 'Element')
{
.......
}
if (ClassType(C) == 'etc')
{
.......
}

Something like this is possible, provided that you actually do store
pointers in your list and you don't return a void* from your Get function.
Also, your Element class would need to have at least one virtual member
function. You would have to return an Element*, then you could do:

Element* C = S.Get(3);
if (typeid(*C) == typeid(FSet))
{
//...
}
else if (typeid(*C) == typeid(Element))
{
//...
}

However it is in most cases considered bad design. You should put the
differences into virtual member functions of your element class. This is
more efficient, easier to read and more maintainable.
I'm not sure if its possible to do this or not ;/ (I'm sure its possible,
but not sure if C++ keeps track of class types and there instantiation(I
doubt it does)).

It does for polymorphic types, as long as you stay within one class
hierarchy.
If what I'm trying to do is not possible the way I am doing it, is there
another way? I want to create a class that represents a set of "arbitrary
elements"(i.e. any class type, not just of one type).

Really "any" class? What do you think you need that for? What do you do if
you get something of a type you didn't expect?
Anyway, if you really need it (and I doubt you do), then you could have a
look at boost's "any" class. See http://www.boost.org/doc/html/any.html
 
K

Kristo

Is there any way to get the class type from a pointer?

Yes, there is, but you should stop and ask yourself if you *really* want
to do this. Often, the best solution is to rethink your design rather
than "ask" an object what its type is. The latter usually leads to
unmaintainable chains of if-elses as your program grows.
I'm working on a class that acts as a set:

I have two classes, one called FSet and the other called Element.

FSet inherets Element and has an internal pointer to a list of pointer of
Element type.

That sounds a little strange. It sounds like an FSet is a container of
Elements. Inheritance normally implies an is-a relationship, i.e., an
FSet is a kind of Element. You can probably do without the inheritance.
I have method in FSet that adds an Element to the list(does memory
management and checks if its already there).


So, I might I can do something like this:

FSet S;
FSet S1;
SomeClass C;
Element A, B, C;

S.Add(A);
S.Add(B);
S.Add(C);
S.Add((Element)S);
S.Add((Element)C);

I think you have at least one typo in there. You can't have two objects
in the same scope named C. Furthermore, why would you want to add the
entire set to itself? (fourth call to Add)
Now, I would like to write a method that lets me get an element from the
list, but I would also need to know what class type it is.

i.e. I would need something like:

void *C = S.Get(3);

if (ClassType(C) == 'FSet')
{
.........
}
if (ClassType(C) == 'Element')
{
.......
}
if (ClassType(C) == 'etc')
{
.......
}

This is exactly what I was talking about above. As the number of
different ClassTypes grows, your code quickly becomes unmaintainable
(and unreadable).
I'm not sure if its possible to do this or not ;/ (I'm sure its possible,
but not sure if C++ keeps track of class types and there instantiation(I
doubt it does)).


If what I'm trying to do is not possible the way I am doing it, is there
another way? I want to create a class that represents a set of "arbitrary
elements"(i.e. any class type, not just of one type).

It sounds like what you want is a heterogeneous container. While it is
not directly possible to create one in C++, you can approximate it
pretty well. See the C++ FAQ entry here:
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.4

Experiment with the ideas presented there for a while and feel free to
come back if you have questions. Be sure to post a minimal *compilable*
example next time.

Kristo
 
J

Jon Slaughter

Rolf Magnus said:
I don't see any pointer in your example.

I use the pointers interally to keep track of the elements in the set. The
set is dynamically managed by internal routines.

Don't use C style casts. Generally, you should need a cast only rarely,
and
then, use the appropriate C++ cast (dynamic_cast, static_cast, const_cast
or reinterpret_cast).
Also, this will probably not do what you want. It will create a new object
of class Element and copy only the Element part of S into that object.
This
is called slicing.


It is Element, since you stored only objects of that type in your
container.


Don't use pointers to void.

It was just an example, since I'm not sure how I can could return on object
such as Element and then it also be something else.
Something like this is possible, provided that you actually do store
pointers in your list and you don't return a void* from your Get function.
Also, your Element class would need to have at least one virtual member
function. You would have to return an Element*, then you could do:

Element* C = S.Get(3);
if (typeid(*C) == typeid(FSet))
{
//...
}
else if (typeid(*C) == typeid(Element))
{
//...
}

However it is in most cases considered bad design. You should put the
differences into virtual member functions of your element class. This is
more efficient, easier to read and more maintainable.


It does for polymorphic types, as long as you stay within one class
hierarchy.


Really "any" class? What do you think you need that for? What do you do if
you get something of a type you didn't expect?
Anyway, if you really need it (and I doubt you do), then you could have a
look at boost's "any" class. See http://www.boost.org/doc/html/any.html


Ok, I will have a look.

Thanks.
Jon
 
J

Jon Slaughter

Kristo said:
Yes, there is, but you should stop and ask yourself if you *really* want
to do this. Often, the best solution is to rethink your design rather
than "ask" an object what its type is. The latter usually leads to
unmaintainable chains of if-elses as your program grows.


That sounds a little strange. It sounds like an FSet is a container of
Elements. Inheritance normally implies an is-a relationship, i.e., an
FSet is a kind of Element. You can probably do without the inheritance.


The reason I do this is because a set can be an element too. i.e., a you
can have a set of sets.

So, FSet is a kinda of Element.

i.e.,

S = {a, b, {c,d}}

{c,d} is a set contained in S, but it is an element of S.

I think you have at least one typo in there. You can't have two objects
in the same scope named C. Furthermore, why would you want to add the
entire set to itself? (fourth call to Add)

Yes, heh, I wan't paying attention ;/
This is exactly what I was talking about above. As the number of
different ClassTypes grows, your code quickly becomes unmaintainable (and
unreadable).


Yes, I understand that, but I really don't see how I can return an arbitrary
element from my set and be able to access its members without knowing what
type it is. I will explain in more detail what I am trying to do at the end.

It sounds like what you want is a heterogeneous container. While it is
not directly possible to create one in C++, you can approximate it pretty
well. See the C++ FAQ entry here:
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.4

yes, that is basicaly what I'm trying to do. i.e., I don't want to just have
a Set of only one possible type.
Experiment with the ideas presented there for a while and feel free to
come back if you have questions. Be sure to post a minimal *compilable*
example next time.

Kristo


Yeah, I have to learn more about C++. I haven't programmed much in a couple
of years and I've forgot a lot of things too ;/


Ok, hopefully this will make my problem more clear:


In mathematics, as you probably know, Sets(A collection of "things") are
used all the time. A set and element tend to be taken as undefined terms.

Now, I want to implement a set in C++ so I can do some math with it. I need
a way to store and retrieve "elements" of that set. But the elements can be
anything such as a number, array, or class.

Basicaly, I need to implement Set theory in C++.

I need have have a way to store elements(which can be anything), check for
inclusion, and have the normal set theory operations. This should be
relatively easy to do.

The problem I have, is that if I take an arbitrary element from the set
without knowing its type, but needing to handle that element.

For example,

S = {x | x is a fruit or x is a real number}

now, if I have an object y, its easy to see if y is in S(well, assuming I
can only have unique objects in my universe(so I can do a pointer
comparision)), but if I have an object y in S, how do I test if it is a real
number of a fruit? Lets say on fruits I might want to print out what kind
they are and if it is a real number I might want to print its value.

So, as I've said before, the way I would do it, which you guys say is
bad(which is probably right but its only way I know how ;/) is to use
something liek a switch statement over all possible types.

The problem is, if I do

x = S.Some_Random_Element_In_S();

x.Display_Fruit_Name();

will fail and even if I did a typecast, it would probably crash if x is a
real number.



So, probably my main problem is that I don't understand much of the
capabilities of C++. I guess I need to go study up on some of its
features(I've always thought of C++ as just C with classes, but it seems
that it is much more). Do you have any recommendations on where I should
start to get a better grasp on what i'm trying to do?

Thanks.

Jon
 
K

Kristo

In mathematics, as you probably know, Sets(A collection of "things") are
used all the time. A set and element tend to be taken as undefined terms.

Now, I want to implement a set in C++ so I can do some math with it. I need
a way to store and retrieve "elements" of that set. But the elements can be
anything such as a number, array, or class.

Basicaly, I need to implement Set theory in C++.

I need have have a way to store elements(which can be anything), check for
inclusion, and have the normal set theory operations. This should be
relatively easy to do.

The problem I have, is that if I take an arbitrary element from the set
without knowing its type, but needing to handle that element.

For example,

S = {x | x is a fruit or x is a real number}

now, if I have an object y, its easy to see if y is in S(well, assuming I
can only have unique objects in my universe(so I can do a pointer
comparision)), but if I have an object y in S, how do I test if it is a real
number of a fruit? Lets say on fruits I might want to print out what kind
they are and if it is a real number I might want to print its value.

It seems like your case is a perfect candidate for a hierarchy of
handles (see FAQ 34.4). Imagine a class structure like this:

Handle
/ | \
/ | \
/ | \
FruitHandle SetHandle NumberHandle

Now, let's make Handle an abstract base class. In it, place pure
virtual functions for every operation you want to do on an element of
your set, such as printing and checking for equality. Then you
implement these functions in the child classes. Finally, to build your
main set, you could use a std::set<Handle *>. However, this leads to
the problem of freeing the different Handle objects. You could wrap the
std::set<Handle *> in a special class whose destructor calls the
destructor of each element in the set. Alternatively, if you have
access to the Boost library, you could use a
std::set<boost::shared_ptr<Handle> > which would handle the memory
management for you.

Using this design, a FruitHandle would contain a Fruit object, a
NumberHandle would contain an int (or double or whatever), and a
SetHandle would contain a std::set<Handle *> (or the Boost version).
Notice that SetHandle cleanly takes care of the concept of recursive
sets. The only catch is what you plan on doing with the elements
themselves. As long as the operations can be limited to member
functions of Handle, this design should suffice. If you need to get the
elements *out* of the set, you might be stuck with figuring out what
type of Handle pointer you have. The other part of FAQ 34.4 should help
with this.
So, probably my main problem is that I don't understand much of the
capabilities of C++. I guess I need to go study up on some of its
features(I've always thought of C++ as just C with classes, but it seems
that it is much more). Do you have any recommendations on where I should
start to get a better grasp on what i'm trying to do?

Using C++ as a better C is an easy way for a long time C programmer to
"get his feet wet." However, if you're really interested in learning
C++ and object-oriented programming, I suggest unlearning all of your C
habits. See FAQ section 28 for some good resources that will get you
started.

Set Theory is a hard problem in C++ because it is a statically typed
language. That is, the type of an object is determined at compile time.
This makes it difficult to implement a container of "anything."
Dynamically typed languages such as Perl and OCaml are much better at
this sort of thing.

Kristo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,055
Members
47,659
Latest member
salragu

Latest Threads

Top