Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   How can I remove dynamic_cast and if statements from this code snippet? (http://www.velocityreviews.com/forums/t805997-how-can-i-remove-dynamic_cast-and-if-statements-from-this-code-snippet.html)

Chris Stankevitz 11-16-2011 06:37 PM

How can I remove dynamic_cast and if statements from this code snippet?
 
Hello,

I would like to remove the "dynamic_cast" and "if" statements from the
code below. I believe some people would describe this as making the
code "polymorphic". Can you recommend a way to do this without
modifying the original classes in "Library A"?

My intention is to create an "XML Writer" class(es) for shapes without
putting "XML code" in the base classes. I plan to use a similar
pattern for drawing and other tasks my application has to perform on
Shape objects.

Thank you,

Chris

// Library A
struct Shape { virtual ~Shape() {} };
struct Circle : public Shape { float radius; };
struct Square : public Shape { float edge; };

// Library B
#include <iostream>

class XmlWriter
{
static void write(Shape* shape)
{
if (Circle* circle = dynamic_cast<Circle*>(shape))
{
std::cout << "<Circle Radius=" << circle->radius << "/>";
}
else if (Square* square = dynamic_cast<Square*>(shape))
{
std::cout << "<Square Edge=" << square->edge << "/>";
}
}
};

Ian Collins 11-16-2011 06:52 PM

Re: How can I remove dynamic_cast and if statements from this codesnippet?
 
On 11/17/11 07:37 AM, Chris Stankevitz wrote:
> Hello,
>
> I would like to remove the "dynamic_cast" and "if" statements from the
> code below. I believe some people would describe this as making the
> code "polymorphic". Can you recommend a way to do this without
> modifying the original classes in "Library A"?
>
> My intention is to create an "XML Writer" class(es) for shapes without
> putting "XML code" in the base classes. I plan to use a similar
> pattern for drawing and other tasks my application has to perform on
> Shape objects.
>
> Thank you,
>
> Chris
>
> // Library A
> struct Shape { virtual ~Shape() {} };
> struct Circle : public Shape { float radius; };
> struct Square : public Shape { float edge; };
>
> // Library B
> #include<iostream>
>
> class XmlWriter
> {
> static void write(Shape* shape)
> {
> if (Circle* circle = dynamic_cast<Circle*>(shape))
> {
> std::cout<< "<Circle Radius="<< circle->radius<< "/>";
> }
> else if (Square* square = dynamic_cast<Square*>(shape))
> {
> std::cout<< "<Square Edge="<< square->edge<< "/>";
> }
> }
> };


Something like:

struct Shape {
virtual void write() = 0;
};
struct Circle : public Shape {
float radius;
void write()
{
std::cout<< "<Circle Radius="<< circle->radius<< "/>";
}
};

struct Square : public Shape {
float edge;
void write()
{
std::cout<< "<Square Edge="<< square->edge<< "/>";
}
};

class XmlWriter
{
static void write(Shape* shape)
{
shape->write();
}
};

--
Ian Collins

Chris Stankevitz 11-16-2011 07:14 PM

Re: How can I remove dynamic_cast and if statements from this code snippet?
 
On Nov 16, 10:52*am, Ian Collins <ian-n...@hotmail.com> wrote:
> Something like:
>
> struct Shape {
> * *virtual void write() = 0;};


Ian,

I prefer/require a solution in which the shapes themselves are not
writing out XML -- I want the XML related code restricted to the
"XmlWriter" class in "Library B". This appears to be an overly
draconian requirement in this simple example, but should make more
sense if you consider adding something like a "drawing" or "network"
class that would introduce dependencies on drawing or socket code.

I want drawing/xml/socket code relegated to "Library B" without
compile or link dependencies in "Library A".

Thank you,

Chris

red floyd 11-16-2011 08:03 PM

Re: How can I remove dynamic_cast and if statements from this codesnippet?
 
On 11/16/2011 11:14 AM, Chris Stankevitz wrote:
> On Nov 16, 10:52 am, Ian Collins<ian-n...@hotmail.com> wrote:
>> Something like:
>>
>> struct Shape {
>> virtual void write() = 0;};

>
> Ian,
>
> I prefer/require a solution in which the shapes themselves are not
> writing out XML -- I want the XML related code restricted to the
> "XmlWriter" class in "Library B". This appears to be an overly
> draconian requirement in this simple example, but should make more
> sense if you consider adding something like a "drawing" or "network"
> class that would introduce dependencies on drawing or socket code.
>
> I want drawing/xml/socket code relegated to "Library B" without
> compile or link dependencies in "Library A".
>



You are somewhat correct here. Have the "write" function return
a string which the XML code can display. By divorcing the I/O from
the representation return, you're more general anyways.

BTW, what book are you reading? This fragment/problem is actually
one of the canonical OOP examples.

class Shape {
public:
//...
virtual std::string as_string() = 0;
}

class Square {
//...
std::string as_string() { return "Edge..." };
}

class


Chris Stankevitz 11-16-2011 09:28 PM

Re: How can I remove dynamic_cast and if statements from this code snippet?
 
On Nov 16, 12:03*pm, red floyd <no.spam.h...@its.invalid> wrote:
> You are somewhat correct here. *Have the "write" function return
> a string which the XML code can display. *By divorcing the I/O from
> the representation return, you're more general anyways.


Red,

Thank you for your reply. I believe you have attempted to solve my
problem by modifying the original shapes to return their "XML
components" as strings.

Unfortunately this is not what I am interested in because it does not
scale to what I really want to do. Instead of writing a long-winded
response that might not come across correctly, allow me to change my
original question to use drawing instead of string writing:

===

Is it possible in C++ to modify "Library B" below to eliminate the
dynamic_cast and switch statements, while at the same time not doing
any of the following:
- Do not use DeviceContext in "Library A"
- Do not put drawing code in "Library A"
- Do not put the concept of drawing into "Library A" including adding
a class Shape::GetPixelsToDraw

My goal is to
a) not put any reference to drawing into Library A
b) not use dynamic_cast or switch/if blocks in Library B

The answer might be something like "use factories" or "use template"
or "this is not possible in c++".

Thank you,

Chris


// Library A
struct Shape { virtual ~Shape() {} };
struct Circle : public Shape { float radius; };
struct Square : public Shape { float edge; };

// Library B

#include <cmath>
struct DeviceContext { void FillPixel(int PixelX, int PixelY) {}; };

class Drawer
{
static void write(Shape* shape, DeviceContext& Dc)
{
if (Circle* circle = dynamic_cast<Circle*>(shape))
{
for (float Angle = 0; Angle < 2*3.14156; Angle += 0.1)
{
Dc.FillPixel(cos(Angle) * circle->radius, sin(Angle) * circle-
>radius);

}
}
else if (Square* square = dynamic_cast<Square*>(shape))
{
Dc.FillPixel(0, 0);
Dc.FillPixel(square->edge, 0);
Dc.FillPixel(square->edge, square->edge);
Dc.FillPixel(0, square->edge);
}
}
};

Ian Collins 11-16-2011 09:37 PM

Re: How can I remove dynamic_cast and if statements from this codesnippet?
 
On 11/17/11 08:14 AM, Chris Stankevitz wrote:
> On Nov 16, 10:52 am, Ian Collins<ian-n...@hotmail.com> wrote:
>> Something like:
>>
>> struct Shape {
>> virtual void write() = 0;};

>
> Ian,
>
> I prefer/require a solution in which the shapes themselves are not
> writing out XML -- I want the XML related code restricted to the
> "XmlWriter" class in "Library B". This appears to be an overly
> draconian requirement in this simple example, but should make more
> sense if you consider adding something like a "drawing" or "network"
> class that would introduce dependencies on drawing or socket code.
>
> I want drawing/xml/socket code relegated to "Library B" without
> compile or link dependencies in "Library A".


Well you have to look seriously at whether a shape knows how to write
its self, or an XmlWriter knows how to write a shape. If it's the
latter, you gave to provide a means for an XmlWriter to access the
required information. This can lead to significant complexity and
coupling in your design.

It gets more complex still if you consider drawing a shape.

--
Ian Collins

Chris Stankevitz 11-16-2011 09:38 PM

Re: How can I remove dynamic_cast and if statements from this code snippet?
 
On Nov 16, 12:35*pm, Leigh Johnston <le...@i42.co.uk> wrote:
> * * * * virtual void write(const serializer& writer) const



Leigh,

Thank you for your reply. I believe you have effectively modified the
base class to return the XML components as strings. This is not what
I am attempting to do as it requires me to modify the base class to
assume it will be serialized. I'm looking for an approach in which the
base class is not modified or at least is modified only in a way that
allows a Factory or Template or some other technique to give shape
details to another library. I do not want to modify the base class to
share "serializing" details. I try to explain this a little better in
my reply to Red.

Thank you,

Chris


Chris Stankevitz 11-16-2011 09:41 PM

Re: How can I remove dynamic_cast and if statements from this code snippet?
 
On Nov 16, 1:37*pm, Ian Collins <ian-n...@hotmail.com> wrote:
> Well you have to look seriously at whether a shape knows how to write
> its self, or an XmlWriter knows how to write a shape. *If it's the
> latter, you have to provide a means for an XmlWriter to access the
> required information.


Yes, it is the latter that I would like to do.

>*This can lead to significant complexity


Yes, I am looking for complexity and am curious if it is possible to
do this with c++.

> It gets more complex still if you consider drawing a shape.


Yes, I am trying to draw Shapes without Shapes knowing how to draw
themselves. Is it possible to do this in c++ without using
dynamic_cast or lots of switch/if statements?

Thank you,

Chris

Chris Stankevitz 11-16-2011 09:46 PM

Re: How can I remove dynamic_cast and if statements from this code snippet?
 
On Nov 16, 1:39*pm, Leigh Johnston <le...@i42.co.uk> wrote:
> struct DrawableCircle : Circle, Drawable


Unfortunately the object that creates my shapes cannot create
DrawableShapes as that library has no dependency on or knowledge of
the concept of drawing. But thank you for continuing to attempt to
help me.

Chris

Ian Collins 11-16-2011 09:56 PM

Re: How can I remove dynamic_cast and if statements from this codesnippet?
 
On 11/17/11 10:41 AM, Chris Stankevitz wrote:
> On Nov 16, 1:37 pm, Ian Collins<ian-n...@hotmail.com> wrote:
>> Well you have to look seriously at whether a shape knows how to write
>> its self, or an XmlWriter knows how to write a shape. If it's the
>> latter, you have to provide a means for an XmlWriter to access the
>> required information.

>
> Yes, it is the latter that I would like to do.
>
>> This can lead to significant complexity

>
> Yes, I am looking for complexity and am curious if it is possible to
> do this with c++.
>
>> It gets more complex still if you consider drawing a shape.

>
> Yes, I am trying to draw Shapes without Shapes knowing how to draw
> themselves. Is it possible to do this in c++ without using
> dynamic_cast or lots of switch/if statements?


The problem has little to do with C++. The issue of who knows how to do
what is common to any language.

The literal answer to your question is yes. You can always replace
conditionals with virtual member functions.

--
Ian Collins


All times are GMT. The time now is 04:19 PM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57