S
Suzanne Vogel
Hi,
I've been trying to write a function to test whether one class is
derived from another class. I am given only id's of the two classes.
Therefore, direct use of template methods is not an option.
Let's call the id of a class "cid" (for "class id").
The function signature should look like this:
******************************************
bool isDerivedFrom(cid child, cid parent);
******************************************
I see two basic options:
(1) Test whether we can typecast from an instance of the child class to
an instance of the parent class. If the typecast fails (by returning
NULL or throwing an exception), then we know that the child is *not*
derived from the parent. eg,
(a) Use dynamic_cast<> (somehow), since it throws an exception if
you try to cast to a non-parent class.
(2) Manually (as preprocessing) build a tree structure of id's that
parallels the actual class hierarchy, to examine later during runtime.
I would *much* prefer option#1, since it is more extensible. However, it
is difficult to figure out how, since it requires templates under the
hood, and these must be abstracted away to cid's in the final function
signature. That is why I am writing to this newsgroup.
Perhaps under the hood, we can use dynamic_cast<> in a helper function:
template<class TChild, class TParent>
bool isDerivedFrom()
{
TChild* child = new TChild();
try
{ dynamic_cast<TParent*>(child);
}
catch(exception&) { return false; }
return true;
}
************************************************************************************
How can I get the 'isDerivedFrom(cid child, cid parent)' function to
call this templated version appropriately?
************************************************************************************
Here are the utilities that I have to work with:
(1) A generic IObj superclass, as parent to all classes in the system.
Each subclass has an associated cid and implements a virtual getter
function for it:
const cid IObj::getCID(); //get the cid for this class
(2) A mapping from cid's to create functions which return an instance of
the specified class, as an IObj* pointer:
IObj* getNewObj(cid c);
(3) (probably not useful in this case) A mapping from cid's to strings
representing class names:
string& getClassName(cid c);
Here are some problems I discovered in my implementation attempts, which
we need to be aware of:
(1) Casting from IObj* always fails via dynamic_cast<> (since IObj is
parent to every class, and dynamic_cast<> can only cast from child classes).
(2) Casting from void* always succeeds via C-cast (since it is totally
non-typesafe) and cannot be done at all via dynamic_cast<>.
For instance, I tried this, but it always fails due to #1:
template<class TParent>
bool isDerivedFrom(cid child)
{
IObj* childObj = getNewObj(child);
try
{ dynamic_cast<TParent*>(childObj); //always fails, since childObj
is a ptr to IObj, *not* a ptr to whatever its ultimate derived type is
}
catch(exception&) { return false; }
return true;
}
The real magic would be to use ***MACROS***, to temporarily forgo uses
of IObj.
************************************************************************************
How can I implement the macro(s) "MACRO_GET_CLASS_NAME" and/or
"MACRO_GET_CHILD_OBJ" below?
************************************************************************************
MAGIC #1. (How can I implement the macros here?)
bool isDerivedFrom(cid child, cid parent)
{
try
{
dynamic_cast<MACRO_GET_CLASS_NAME(parent)>(MACRO_GET_CHILD_OBJ(child));
}
catch(exception&) { return false; }
return true;
}
MAGIC #2. (How can I implement the macro here?)
template<class T>
class WrapperClass
{
static bool isDerivedFrom(cid child) // this func ptr can be stored
*non-templated* in a map of (cid, static funcs), so it's useful
{
try
{ dynamic_cast<T>(MACRO_GET_CHILD_OBJ(child));
}
catch(exception&) { return false; }
return true;
}
};
I tried the following, but attempting to use them in "MAGIC #1" and
"MAGIC#2" did not compile. I also *hate* them because they require
exhaustively listing class id's,
which is not very extensible (eg, if someone else wants to add classes
to my program).
#define MACRO_GET_CLASS_NAME(id) ( \
id == kCID_Foo ? Foo \
: id == kCID_Bar ? Bar \
: NILL )
#define MACRO_GET_CHILD_OBJ(id) ( \
( id == kCID_Foo ? new Foo() \
: id == kCID_Bar ? new Bar() \
: NULL ) )
(Please ignore the memory leaks resulting from using "new" without using
"delete" here. I had a solution to prevent that, but it's not worth
cluttering my questions here by presenting it. )
Aaargh! Where's a hack when you need one? :-( I'm about to hack out my
brains.
Thanks for any suggestions.
Suzanne
I've been trying to write a function to test whether one class is
derived from another class. I am given only id's of the two classes.
Therefore, direct use of template methods is not an option.
Let's call the id of a class "cid" (for "class id").
The function signature should look like this:
******************************************
bool isDerivedFrom(cid child, cid parent);
******************************************
I see two basic options:
(1) Test whether we can typecast from an instance of the child class to
an instance of the parent class. If the typecast fails (by returning
NULL or throwing an exception), then we know that the child is *not*
derived from the parent. eg,
(a) Use dynamic_cast<> (somehow), since it throws an exception if
you try to cast to a non-parent class.
(2) Manually (as preprocessing) build a tree structure of id's that
parallels the actual class hierarchy, to examine later during runtime.
I would *much* prefer option#1, since it is more extensible. However, it
is difficult to figure out how, since it requires templates under the
hood, and these must be abstracted away to cid's in the final function
signature. That is why I am writing to this newsgroup.
Perhaps under the hood, we can use dynamic_cast<> in a helper function:
template<class TChild, class TParent>
bool isDerivedFrom()
{
TChild* child = new TChild();
try
{ dynamic_cast<TParent*>(child);
}
catch(exception&) { return false; }
return true;
}
************************************************************************************
How can I get the 'isDerivedFrom(cid child, cid parent)' function to
call this templated version appropriately?
************************************************************************************
Here are the utilities that I have to work with:
(1) A generic IObj superclass, as parent to all classes in the system.
Each subclass has an associated cid and implements a virtual getter
function for it:
const cid IObj::getCID(); //get the cid for this class
(2) A mapping from cid's to create functions which return an instance of
the specified class, as an IObj* pointer:
IObj* getNewObj(cid c);
(3) (probably not useful in this case) A mapping from cid's to strings
representing class names:
string& getClassName(cid c);
Here are some problems I discovered in my implementation attempts, which
we need to be aware of:
(1) Casting from IObj* always fails via dynamic_cast<> (since IObj is
parent to every class, and dynamic_cast<> can only cast from child classes).
(2) Casting from void* always succeeds via C-cast (since it is totally
non-typesafe) and cannot be done at all via dynamic_cast<>.
For instance, I tried this, but it always fails due to #1:
template<class TParent>
bool isDerivedFrom(cid child)
{
IObj* childObj = getNewObj(child);
try
{ dynamic_cast<TParent*>(childObj); //always fails, since childObj
is a ptr to IObj, *not* a ptr to whatever its ultimate derived type is
}
catch(exception&) { return false; }
return true;
}
The real magic would be to use ***MACROS***, to temporarily forgo uses
of IObj.
************************************************************************************
How can I implement the macro(s) "MACRO_GET_CLASS_NAME" and/or
"MACRO_GET_CHILD_OBJ" below?
************************************************************************************
MAGIC #1. (How can I implement the macros here?)
bool isDerivedFrom(cid child, cid parent)
{
try
{
dynamic_cast<MACRO_GET_CLASS_NAME(parent)>(MACRO_GET_CHILD_OBJ(child));
}
catch(exception&) { return false; }
return true;
}
MAGIC #2. (How can I implement the macro here?)
template<class T>
class WrapperClass
{
static bool isDerivedFrom(cid child) // this func ptr can be stored
*non-templated* in a map of (cid, static funcs), so it's useful
{
try
{ dynamic_cast<T>(MACRO_GET_CHILD_OBJ(child));
}
catch(exception&) { return false; }
return true;
}
};
I tried the following, but attempting to use them in "MAGIC #1" and
"MAGIC#2" did not compile. I also *hate* them because they require
exhaustively listing class id's,
which is not very extensible (eg, if someone else wants to add classes
to my program).
#define MACRO_GET_CLASS_NAME(id) ( \
id == kCID_Foo ? Foo \
: id == kCID_Bar ? Bar \
: NILL )
#define MACRO_GET_CHILD_OBJ(id) ( \
( id == kCID_Foo ? new Foo() \
: id == kCID_Bar ? new Bar() \
: NULL ) )
(Please ignore the memory leaks resulting from using "new" without using
"delete" here. I had a solution to prevent that, but it's not worth
cluttering my questions here by presenting it. )
Aaargh! Where's a hack when you need one? :-( I'm about to hack out my
brains.
Thanks for any suggestions.
Suzanne