473,386 Members | 1,734 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Can I avoid rewriting this function in a subclass?

Hi,

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?

Or is there just a better way to do this altogether?
Thanks

Steve
Apr 1 '06 #1
6 1260
On Sat, 01 Apr 2006 10:28:47 +0100, Steve Edwards wrote:
Hi,

I'm trying to find a simple way to identify which of a heirachy of
classes a particular class is:


Use the built-in RTTI operations (dynamic_cast<T> and friends), or, better
yet, scrap the design and rebuild it. Needing to know which subclass
something is is almost invariably a sign that you shouldn't be using
inheritance at all.

What's the real problem you're solving?
Apr 1 '06 #2

Owen Jacobson wrote:
On Sat, 01 Apr 2006 10:28:47 +0100, Steve Edwards wrote:
Hi,

I'm trying to find a simple way to identify which of a heirachy of
classes a particular class is:


Use the built-in RTTI operations (dynamic_cast<T> and friends), or, better
yet, scrap the design and rebuild it. Needing to know which subclass
something is is almost invariably a sign that you shouldn't be using
inheritance at all.

What's the real problem you're solving?


It's a natural-language-understanding app, and the classes represent
real world heirarchical objects i.e. poodle isa dog isa mammal isa
animal isa living-thing etc.
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().

Thanks

Steve

Apr 1 '06 #3
"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
Apr 1 '06 #4

Ivan Vecerina wrote:
"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);
}


Thanks Ivan, that covers all that I need to do. A quick Googling seems
to show that typeid might be faster than dynamic_cast, as it's a fixed
execution time, as opposed to being dependent on how deep the class
heirarch is (?). I'll use both methods you showed and see if there's
any perceptible performance difference.

Apr 1 '06 #5
In message <11**********************@u72g2000cwu.googlegroups .com>,
Steve555 <fo*******@btinternet.com> writes

Owen Jacobson wrote:
On Sat, 01 Apr 2006 10:28:47 +0100, Steve Edwards wrote:
> Hi,
>
> I'm trying to find a simple way to identify which of a heirachy of
> classes a particular class is:


Use the built-in RTTI operations (dynamic_cast<T> and friends), or, better
yet, scrap the design and rebuild it. Needing to know which subclass
something is is almost invariably a sign that you shouldn't be using
inheritance at all.

What's the real problem you're solving?


It's a natural-language-understanding app, and the classes represent
real world heirarchical objects i.e. poodle isa dog isa mammal isa
animal isa living-thing etc.
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().

The obvious[*] solution to _that_ is to have functions such as:

virtual bool CanBark() const;

etc.
[*] Not necessarily a good one ;-(

--
Richard Herring
Apr 6 '06 #6
Richard Herring wrote:
In message <11**********************@u72g2000cwu.googlegroups .com>,
Steve555 <fo*******@btinternet.com> writes

Owen Jacobson wrote:
On Sat, 01 Apr 2006 10:28:47 +0100, Steve Edwards wrote:
....
What's the real problem you're solving?


It's a natural-language-understanding app, and the classes represent
real world heirarchical objects i.e. poodle isa dog isa mammal isa
animal isa living-thing etc.
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().

The obvious[*] solution to _that_ is to have functions such as:

virtual bool CanBark() const;

etc.

[*] Not necessarily a good one ;-(


Perhaps further abstraction of the operation is required:

virtual void Communicate()const;

Jeff
Apr 6 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Gerry Sutton | last post by:
Hi All! I have noticed a strange behavior when using a constant identifier to initialize an instance list variable in a base class and then trying to modifying the list in subclasses by using...
3
by: Jamie Jackson | last post by:
I'm rewriting all links' onclick events, but I'm having a problem. The onclick event that I'm inserting works correctly in Opera, but not in FF or IE. I'm retroactively adding the statement...
6
by: Nels Olsen | last post by:
Our company is rewriting our product in .NET. The old product is in PowerBuilder, which is heavy on Hungarian notation. We are approaching the time where we have to finalize naming conventions for...
0
by: Lee | last post by:
Hi all ;) Preamble -------- I'm using URL rewriting to enforce a frames policy (yeah, I know frames are 'bad' :) - i.e. if a request comes in for a page which should be nested within a...
0
by: Netveloper | last post by:
Hi, I'm playing around with url rewriting and I have come across a problem which I can't seem to get past. The general ide is to have a IHttpHandlerFactory class which checks the incoming...
9
by: sashang | last post by:
Hi I'd like to use metaclasses to dynamically generate a class based on a parameter to the objects init function. For example: class MetaThing(type): def __init__(cls, name, bases, dict,...
1
by: Greg Collins [Microsoft MVP] | last post by:
I have a site that uses a custom 404 error page to perform URL Rewriting. This works excellent for all my needs except for one area. When transforming XML, I have some XSLT code that uses the...
10
by: blangela | last post by:
If I pass a base class object by reference (likely does not make a difference here that it is passed by reference) as a parameter to a derived class member function, the member function is not...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.