"Steve Edwards" <gf*@lineone.net> wrote in message
news:gf***********************@europe.isp.giganews .com...
: I'm trying to find a simple way to identify which of a heirachy of
: classes a particular class is:
:
: class Agent
: {
: public:
: enum { class_ID = 'Agnt' };
: Agent();
: virtual ~Agent(){};
: virtual string ClassID();
:
: protected:
: };
:
: //----------------------------
: string Agent::ClassID()
: {
: char id[4] = {(char)(class_ID>>24), (char)(class_ID>>16),
: (char)(class_ID>>8), (char)class_ID };
: string strID(id, 4);
: return strID;
: }
: //----------------------------
:
: This works, and returns as a string the class_ID "Agnt"
:
: But then I declare subclasses, such as:
:
: class SubAgent : public Agent
: {
: public:
: enum { class_ID = 'SubA' };
: (SubAgent);
: virtual ~ SubAgent(){};
:
: protected:
: };
:
:
: Now if I examine SubAgent's class_ID in the debugger I can see that it
: has the correct id = 'SubA'. But if I try to retreive it via ClassID(),
: I get the Super Class's id of "Agnt".
:
: Is the only solution to re-declare and cut'n'paste a copy of ClassID()
: for each of the many sub-classes I have?
For the accessed value of class_ID to be class-specific,
you need a virtual function.
So you could write:
class Agent
{
public:
string ClassID();
private:
virtual unsigned long class_ID() { return 'Agnt'; }
};
string Agent::ClassID()
{
unsigned long v = this->class_ID();
char id[4] = {(char)(v>>24), (char)(v>>16), (char)(v>>8), (char)v };
return string(id, 4);
}
// each subclass overrides the 'class_ID()' function.
: Or is there just a better way to do this altogether?
Why have 'class_ID' both as a string and as a numeric value?
You should be able to drop-out either representation
from the class itself.
+from your previous reply:
: It's a natural-language-understanding app, and the classes represent
: real world hierarchical objects i.e. poodle isa dog isa mammal isa
: animal isa living-thing etc.
dynamic_cast & typeid allow you to find this out at run-time.
: Knowing which subclass something is is the whole point, so that
: semantic inferences can be made; I want to be able to infer all the
: properties of Living_Thing , but at the same time know whether I can
: call Bark() or Talk().
Support for specific functions can also be determined by (multiply)
deriving from interface classes.
Example:
#include <iostream>
using namespace std;
struct IBark {
virtual void bark()=0;
};
class Animal { public: virtual ~Animal()=0; };
inline Animal::~Animal() {}
class Mammal : public Animal { };
class Dog : public Mammal, public IBark {
public: virtual void bark() { cout<<"woof!"<<endl; }
};
void foo( Animal& a )
{
cout << "foo has received a "<<typeid(a).name()<<endl;
Mammal* isMammal = dynamic_cast<Mammal*>(&a); // NULL if not a mammal
if( isMammal!=NULL ) cout<<" It is a Mammal !"<<endl;
Dog* isDog = dynamic_cast<Dog*>(&a); // NULL if not a dog
if( isDog!=NULL ) isDog->bark();
IBark* canBark = dynamic_cast<IBark*>(&a);
if( isDog==NULL && canBark!=NULL ) //barking plant?
canBark->bark();
}
int main()
{
Mammal a;
foo(a);
Dog d;
foo(d);
}
-Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <>
http://www.brainbench.com