473,569 Members | 2,879 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

alternative to RTTI needed

Hi, suppose I have an abstract base class called shape and lots of
subclasses like square, circle, triangle and such. These subclasses may
have subclasses themselves as well, but shape is on top of the
inheritance tree.

Now suppose I want to write a different component to draw these shapes.
By different component I really mean different, so the whole
datastructure can be used by other programs that do not know about the
drawing component. And second, the drawing component may not be able to
draw all shapes. My question is, how should the drawing component look like?

Right now I have something like:

class ShapeDrawer {
void draw(shape *p) {
if (typeid(p) == typeid(circle))
draw(dynamic_ca st<circle>(p));

else if (typeid(p) == typeid(triangle ))
draw(dynamic_ca st<triangle>(p) );

else ...
}

void draw(circle *p) { ... }
void draw(triangle *p) { ... }
}

This works, but doesn't look nice. I don't like the overhead of the
draw(shape *p) function. Is there a way to let the compiler do this? Of
course making draw a virtual function of shape would solve it all, but
that is not possible since it really need to be separate components.

Maurice Termeer
Jul 22 '05 #1
9 2246
Maurice Termeer wrote:
Hi, suppose I have an abstract base class called shape and lots of
subclasses like square, circle, triangle and such. These subclasses
may have subclasses themselves as well, but shape is on top of the
inheritance tree.

Now suppose I want to write a different component to draw these
shapes.
By different component I really mean different, so the whole
datastructure can be used by other programs that do not know about the
drawing component. And second, the drawing component may not be able
to draw all shapes. My question is, how should the drawing component
look like?

[SNIP]

As far as I can tell, you are looking for the Visitor pattern.

http://www.drbob42.com/cbuilder/patterns.htm

--
Attila aka WW
Jul 22 '05 #2
Attila Feher wrote:
Maurice Termeer wrote:
Hi, suppose I have an abstract base class called shape and lots of
subclasses like square, circle, triangle and such. These subclasses
may have subclasses themselves as well, but shape is on top of the
inheritance tree.

Now suppose I want to write a different component to draw these
shapes.
By different component I really mean different, so the whole
datastructu re can be used by other programs that do not know about the
drawing component. And second, the drawing component may not be able
to draw all shapes. My question is, how should the drawing component
look like?


[SNIP]

As far as I can tell, you are looking for the Visitor pattern.

http://www.drbob42.com/cbuilder/patterns.htm


Hm, although that is a better solution than mine, I still don't really
like it. It's kind a general structure to solve this problem, but it
still remains a hack. I would actually want to type something like

void draw(shape *p) {
draw(dynamic_ca st<typeid(p)>(p ));
}

but c++ won't let me.
Jul 22 '05 #3
Maurice Termeer wrote:
Attila Feher wrote:

[SNIP]
As far as I can tell, you are looking for the Visitor pattern.

http://www.drbob42.com/cbuilder/patterns.htm


Hm, although that is a better solution than mine, I still don't really
like it. It's kind a general structure to solve this problem, but it
still remains a hack. I would actually want to type something like

void draw(shape *p) {
draw(dynamic_ca st<typeid(p)>(p ));
}

but c++ won't let me.


It is s much a heck, that it is a Design Pattern, one of the first ones.
You probably want to look at that book:

http://www.amazon.com/exec/obidos/tg...097059720/sr=8
-2/ref=pd_csp_2/103-0081174-9277466?v=glanc e&s=books&n=507 846

or

http://tinyurl.com/43r5l

A Design Pattern is (per definition) the opposite to a hack.

--
Attila aka WW
Jul 22 '05 #4
Attila Feher wrote:
Maurice Termeer wrote:
Attila Feher wrote: [SNIP]
As far as I can tell, you are looking for the Visitor pattern.

http://www.drbob42.com/cbuilder/patterns.htm


Hm, although that is a better solution than mine, I still don't really
like it. It's kind a general structure to solve this problem, but it
still remains a hack. I would actually want to type something like

void draw(shape *p) {
draw(dynamic_ca st<typeid(p)>(p ));
}

but c++ won't let me.


It is s much a heck, that it is a Design Pattern, one of the first ones.
You probably want to look at that book:

http://www.amazon.com/exec/obidos/tg...097059720/sr=8 -2/ref=pd_csp_2/103-0081174-9277466?v=glanc e&s=books&n=507 846

or

http://tinyurl.com/43r5l

A Design Pattern is (per definition) the opposite to a hack.


No. A design pattern is just a hack that is so commonly used that it got
written down as a standard way of solving a problem. That, however, doesn't
mean it's not a hack anymore. Well, I'd not consider all patterns hacks,
but the visitor pattern is not really elegant. Unfortunately, there doesn't
seem to be an elegant C++ solution to the OP's problem.

Jul 22 '05 #5
Dear Maurice,

do you have a copy of "Modern C++ Design" from Andrei Alexandresci? If yes,
just read the chapters about double dispatching. It is not fitting perfectly
but some techniches you could use a described nicely. If you do not have a
copy, take a look inside the dispatching functions in the Loki library which
acompanies the book (http://sourceforge.net/projects/loki-lib/).

If I have some time, I can give you a more extensive answer.

Regards,
Patrick
"Maurice Termeer" <m.*********@st udent.tue.nl> wrote in message
news:ck******** **@news.tue.nl. ..
Hi, suppose I have an abstract base class called shape and lots of
subclasses like square, circle, triangle and such. These subclasses may
have subclasses themselves as well, but shape is on top of the
inheritance tree.

Now suppose I want to write a different component to draw these shapes.
By different component I really mean different, so the whole
datastructure can be used by other programs that do not know about the
drawing component. And second, the drawing component may not be able to
draw all shapes. My question is, how should the drawing component look like?
Right now I have something like:

class ShapeDrawer {
void draw(shape *p) {
if (typeid(p) == typeid(circle))
draw(dynamic_ca st<circle>(p));

else if (typeid(p) == typeid(triangle ))
draw(dynamic_ca st<triangle>(p) );

else ...
}

void draw(circle *p) { ... }
void draw(triangle *p) { ... }
}

This works, but doesn't look nice. I don't like the overhead of the
draw(shape *p) function. Is there a way to let the compiler do this? Of
course making draw a virtual function of shape would solve it all, but
that is not possible since it really need to be separate components.

Maurice Termeer

Jul 22 '05 #6
On Wed, 06 Oct 2004 11:44:32 +0200, Maurice Termeer
<m.*********@st udent.tue.nl> wrote:
Attila Feher wrote:
Maurice Termeer wrote:
Hi, suppose I have an abstract base class called shape and lots of
subclasses like square, circle, triangle and such. These subclasses
may have subclasses themselves as well, but shape is on top of the
inheritanc e tree.

Now suppose I want to write a different component to draw these
shapes.
By different component I really mean different, so the whole
datastructur e can be used by other programs that do not know about the
drawing component. And second, the drawing component may not be able
to draw all shapes. My question is, how should the drawing component
look like?


[SNIP]

As far as I can tell, you are looking for the Visitor pattern.

http://www.drbob42.com/cbuilder/patterns.htm


Hm, although that is a better solution than mine, I still don't really
like it. It's kind a general structure to solve this problem, but it
still remains a hack. I would actually want to type something like

void draw(shape *p) {
draw(dynamic_ca st<typeid(p)>(p ));
}

but c++ won't let me.


That's because you are trying to mix static and dynamic typing. The
above would have to generate a *lot* of code. Note that there are good
generic implementations of the visitor pattern around; check out Loki:
http://sourceforge.net/projects/loki-lib

With that, you won't need to implement any of the boiler-plate code
yourself.

Tom
Jul 22 '05 #7
Rolf Magnus wrote:
[SNIP]
http://tinyurl.com/43r5l

A Design Pattern is (per definition) the opposite to a hack.


No. A design pattern is just a hack that is so commonly used that it
got written down as a standard way of solving a problem. That,
however, doesn't mean it's not a hack anymore. Well, I'd not consider
all patterns hacks, but the visitor pattern is not really elegant.
Unfortunately, there doesn't seem to be an elegant C++ solution to
the OP's problem.


Design Patterns are OW for Good Practice. Hack is the opposite of it. Hack
suggests temporary, not scaling, going-against-the-wind,
only-one-understands etc. Design Patterns are the complete opposite of
that. IIRC there is something called Acyclic Visitor, which is regarded by
many as "what the Visitor pattern really ought to be".

http://www.objectmentor.com/resources/articles/acv.pdf

Maybe that one you do not feel so much of a hack?

--
Attila aka WW
Jul 22 '05 #8
> Of
course making draw a virtual function of shape would solve it all, but
that is not possible since it really need to be separate components.


How separate? Does MI solve your problem?

class Shape
{
public:
virtual ~Shape(){}
};

class DrawableShape
{
public:
virtual void Draw() const = 0;
};

class Circle : public Shape, public DrawableShape
{
virtual void Draw() const
{
foo();
}
};

void Draw(const Shape* s)
{
const DrawableShape* ds = dynamic_cast<co nst DrawableShape*> (s);
if(ds)
ds->Draw();
}

Of course this requires that you are able to change all shape classes to
inherit from DrawableShape. If this is not possible, the Visitor Pattern
might be more suitable.

--
Regards,
Tobias
Jul 22 '05 #9
Maurice Termeer wrote:
Hi, suppose I have an abstract base class called shape and lots of
subclasses like square, circle, triangle and such. These subclasses may
have subclasses themselves as well, but shape is on top of the
inheritance tree.

Now suppose I want to write a different component to draw these shapes.
By different component I really mean different, so the whole
datastructure can be used by other programs that do not know about the
drawing component. And second, the drawing component may not be able to
draw all shapes. My question is, how should the drawing component look
like?

Right now I have something like:

class ShapeDrawer {
void draw(shape *p) {
if (typeid(p) == typeid(circle))
draw(dynamic_ca st<circle>(p));

else if (typeid(p) == typeid(triangle ))
draw(dynamic_ca st<triangle>(p) );

else ...
}

void draw(circle *p) { ... }
void draw(triangle *p) { ... }
}

When people do these sort of things they usually flesh out
the drawer as a seperate object, as it seems you have done.
However let each shape have a draw method:

class Drawer {
draw(Cicle *p);
draw(Rectangle *p);
}

A Shape would have a
void draw(Drawer* d); abstract method, and
the draw implementation of Triangle would just do

void Triangle::draw( Drawer *d){
d->draw(this);
}
Jul 22 '05 #10

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

Similar topics

1
1519
by: MoCha | last post by:
hi all, i want to get the name of the class of an object during run-time. the problem is when i'm using the rtti mechanism of name(), the name is preceded by the length. So, i get something like 3abc (instead of abc). could someone shed some light on this. thanx
9
2039
by: Rick | last post by:
Hi, I wrote a few classes recently and am writing a small GC implementation for C++. I will be implementing my own gc_ptr type maintain a list where I'll store pointers to allocated memory. I was wondering if it is possible to identify objects during runtime via RTTI because I don't want to be doing: gc_ptr<int>::doGC();...
6
1937
by: Kleidemos | last post by:
If I implement a simple RTTI system, more simple than C++ RTTI system for my program and this system is plus or minus: #define DEF_RTTI_BASE(name) virtual inline const char *Name(){ return #name; } #define DEF_RTTI(name) inline const char *Name(){ return #name; } And(for example) class CProva
9
4616
by: Agoston Bejo | last post by:
Hello there, I would like to know what overheads there are to think of when using RTTI. I understand that enabling RTTI increases the sizes of the classes, but not the objects themselves. This doesn't sound too bad. What I'm worried about is whether there is a general performance overhead caused by enabling RTTI, such as enabling exceptions...
2
3770
by: denny | last post by:
Hey all, I know that dynamic_cast<> takes some time, but , for instance, is there a memoy cost associated in with it? Does it have to maintain a table in memory, thus bloating the runtime ram needs of my dll? Does it bloat the actual download size - would my dll be smaller without it? thanks - I'm using rtti in some instances, but I jsut...
3
491
by: Neo | last post by:
Hi Friends, I have a question about RTTI. 1) In C++ we have vptr pointing to vtables which helps to make use of pointer as polymorphic entities. 2) Without knowing object type I can call methods of object using those pointers. So in which case RTTI is needed? ( Why I need to know my object type?) Regards,
5
3018
by: dotNeter | last post by:
I'm studying the RTTI, and my current work is concern for how to get the self-defined type at runtime, that's exactly what the RTTI does. I mean, in my application, I built several self-defined data types, so I have to implement the RTTI by myself. I need a simple and effective example to help me decide how to design. Can someon help me?
33
3540
by: mscava | last post by:
Well I've got a problem, that is more theoretical than practital. I need to know benefits of RTTI. I see another way of doing it... class A { public: ~virtual A() {} enum Type { X, Y, Z }; Type GetType() { return type_; }
2
2238
by: Chameleon | last post by:
I know than dynamic_cast check string name of derived to base class and if one of them match, return the pointer of that object or else zero. I suppose, I dynamic_cast instead of strings, checks integers, then this procedure will be more fast, so I create something like this: --------------------------------------------- class A {...
3
3217
by: lfnovaes | last post by:
Is it possible to get the type of a "unknown" exception using RTTI? Tanks in advance.
0
7619
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7930
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8138
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7681
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7983
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6290
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5228
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3662
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1229
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.