473,597 Members | 2,711 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How would Mr. Stroustrup implement his solution to 12.7[2]

Hi,

I am learning standard C++ as a hobby. The C++ Programming Language :
Special Edition has been the principal source for my information. I read the
entirety of the book and concluded that I had done myself a disservice by
having not attempted and completed the exercises. I intend to rectify that.

My current routine is to read a chapter and then attempt every exercise
problem, and I find that this process is leading to a greater understanding
of the language and implementation.

However, occasionly I am unable to complete some of the exercises, or am not
satisfied with my method of solution. One such exercise is 12.7[2].

From what I read in the chapter and a few papers of his, Mr. Stroustrup
suggests that most of the time the best implemention for the Shape, Dot,
Line, Rectangle hierarchy would be for Shape to be a purely abstract base
class, and for Dot, Line, Rectangle to inheirit from Shape and implement the
virtual functions. In his code examples he routinely defines "virtual void
draw() = 0" as a member of the Shape class. Upon implementing a solution to
12.7[2] I experienced a difficulty surrounding how to implement the drawing
of Shapes for the Window class that must exist. My implementation was for
simple console mode character output using std::cout.

Since I am new to OO programming, I feel that I lack some understanding of
what he intended my solution to be similar to. I have read that it is good
to keep separate ideas, separate. And, using this idea, I run into
difficulty on how to have Dots, Lines, Rectangles, draw themselves, since
they need access to a method of rendering to the screen, but the rendering
must be controlled because I am using console mode character output. Also,
from reading 12.7[5], it seems that the rendering of the shapes needs to
controlled by an intermediary object so that the clipping can be performed.
I am at a loss as to how to complete this exercise in a properly
object-oriented fashion. I wish to understand how to implement C++ in the
best possible way, and that is why I am not satisfied with my current
understanding. If you have the time, and the experience, please share you
knowledge in this matter.

The following is my basic design used to complete 12.7[2], but what I feel
is a very poor design and should not be accepted as a solution. I offer it
in hopes that experienced programmers may better understand my problem, and,
perhaps, offer a better solution. Only the classes Point, Shape, Dot, and
Window will be shown, as their interaction is the same as that for Line, and
Rectangle.

(This is my first post, and I'm not sure how to include a compressed file of
my solution, so please accept this.)

Shape was kept purely abstract, but I added "virtual void draw(Window*
const) const = 0;". I added this because upon implementation I ran into the
problem of how the shapes would be able to access a method of rending to the
screen. What happens is that a Window object, w, has its "draw(Shape *)"
member called. Window::draw(Sh ape*) then passes its "this" pointer to
"Shape::draw(Wi ndow*)". The Shape::draw member then uses the Window pointer
to access Window::put_pix el(Point, char). Window::put_pix el(Point, char)
then adds a pair<Point, char> to a vector object, which is used when
Window::show() is called. The vector is used as a sort of buffer for the
shapes to be drawn to so that multiple shapes can be drawn correctly since I
am using a console mode and cout to render characters.

To draw something, the following would be used:

Window w(10,10);
w.draw(Dot(Poin t(5,5));
w.show();

//*************** ************
// Point.h
// This is a structure because Mr. Stroustrup suggests that classes
// with hidden members, and access members should only be
// used when there is an invariant to enforce, and Point
// does not have an invariant.
// *************** ***********
#ifndef POINT_H
#define POINT_H

struct Point {
Point() :x(0), y(0) { }
Point(int i, int j) :x(i), y(j) { }

int x, y;
};

#endif

// *************** ************
// Shape.h
// Mr. Stroustrup usually declares
// virtual void draw() = 0;
// My design has to pass a Window object.
// *************** ************
#ifndef SHAPE_H
#define SHAPE_H

#include "point.h"

class Window;

struct Shape {
virtual Point n() const = 0;
virtual Point e() const = 0;
virtual Point s() const = 0;
virtual Point w() const = 0;
virtual Point ne() const = 0;
virtual Point nw() const = 0;
virtual Point se() const = 0;
virtual Point sw() const = 0;
virtual ~Shape() {}

virtual void draw(Window* const) const = 0;
};

#endif

// *************** ***************
// Dot.h
// *************** ***************
#ifndef DOT_H
#define DOT_H

#include "point.h"
#include "shape.h"

class Window;

class Dot : public Shape {
public:
Dot();
Dot(const Point&);

Point n() const;
Point e() const;
Point s() const;
Point w() const;
Point ne() const;
Point nw() const;
Point se() const;
Point sw() const;

void draw(Window* const) const;

private:
Point p_;
};

// Inline definitions
inline Point Dot::n() const { return p_; }

inline Point Dot::e() const { return p_; }

inline Point Dot::s() const { return p_; }

inline Point Dot::w() const { return p_; }

inline Point Dot::ne() const { return p_; }

inline Point Dot::nw() const { return p_; }

inline Point Dot::se() const { return p_; }

inline Point Dot::sw() const { return p_; }

#endif

// *************** *****
// Dot.cpp
// *************** *****
#include "dot.h"
#include "window.h"

Dot::Dot() {}

Dot::Dot(const Point& p)
: p_(p)
{
}

void Dot::draw(Windo w* const w) const
{
w->put_pixel(p_ , '*');
}


// *************** *************
// Window.h
// *************** *************
#ifndef WINDOW_H
#define WINDOW_H

#include "point.h"
#include "utility"
#include "vector"

class Shape;

class Window {
public:
Window(const int, const int);

void draw(const Shape&);
Point current() const;
void current(const Point&);
void put_pixel(const Point&, const char&);
void show() const;
void clear();

private:
int w_, h_;
Point c_;
std::vector<std ::pair<Point, char> > points;
};

#endif


// *************** **********
// Window.cpp
// *************** **********
#include "window.h"
#include "shape.h"
#include <iostream>

Window::Window( const int x, const int y)
: w_(x), h_(y) { }

void Window::draw(co nst Shape& s)
{
s.draw(this);
c_ = s.se();
}

Point Window::current () const
{
return c_;
}

void Window::current (const Point& c)
{
c_ = c;
}

void Window::put_pix el(const Point& p, const char& c)
{
points.push_bac k(std::make_pai r(p, c));
}

// This searches the vector for each character position of the window.
// If a character is found, it is written to the screen.
// If a character is not found, a space is written to the screen.
void Window::show() const
{
for (int j=0; j <= h_; j++) {
for (int i=0; i <= w_; i++) {
typedef std::vector<std ::pair<Point,ch ar> >::const_iterat or CI;
CI k;
for (k=points.begin (); k != points.end(); ++k) {
if (k->first.x == i && k->first.y == j) {
std::cout << k->second;
break;
}
}
if (k == points.end()) std::cout << ' ';
}
std::cout << '\n';
}
}

void Window::clear()
{
points.clear();
}
Jul 19 '05 #1
26 3128
Oplec <an*******@anon ymous.com> wrote in message
news:FM******** ***********@twi ster01.bloor.is .net.cable.roge rs.com...
Hi,

I am learning standard C++ as a hobby. The C++ Programming Language :
Special Edition has been the principal source for my information. I read the entirety of the book and concluded that I had done myself a disservice by
having not attempted and completed the exercises. I intend to rectify that.
My current routine is to read a chapter and then attempt every exercise
problem, and I find that this process is leading to a greater understanding of the language and implementation.

However, occasionly I am unable to complete some of the exercises, or am not satisfied with my method of solution. One such exercise is 12.7[2].

From what I read in the chapter and a few papers of his, Mr. Stroustrup
suggests that most of the time the best implemention for the Shape, Dot,
Line, Rectangle hierarchy would be for Shape to be a purely abstract base
class, and for Dot, Line, Rectangle to inheirit from Shape and implement the virtual functions. In his code examples he routinely defines "virtual void
draw() = 0" as a member of the Shape class. Upon implementing a solution to 12.7[2] I experienced a difficulty surrounding how to implement the drawing of Shapes for the Window class that must exist. My implementation was for
simple console mode character output using std::cout.

Since I am new to OO programming, I feel that I lack some understanding of
what he intended my solution to be similar to. I have read that it is good
to keep separate ideas, separate. And, using this idea, I run into
difficulty on how to have Dots, Lines, Rectangles, draw themselves, since
they need access to a method of rendering to the screen, but the rendering
must be controlled because I am using console mode character output. Also,
from reading 12.7[5], it seems that the rendering of the shapes needs to
controlled by an intermediary object so that the clipping can be performed. I am at a loss as to how to complete this exercise in a properly
object-oriented fashion. I wish to understand how to implement C++ in the
best possible way, and that is why I am not satisfied with my current
understanding. If you have the time, and the experience, please share you
knowledge in this matter.

The following is my basic design used to complete 12.7[2], but what I feel
is a very poor design and should not be accepted as a solution. I offer it
in hopes that experienced programmers may better understand my problem, and, perhaps, offer a better solution. Only the classes Point, Shape, Dot, and
Window will be shown, as their interaction is the same as that for Line, and Rectangle.

(This is my first post, and I'm not sure how to include a compressed file of my solution, so please accept this.)

Shape was kept purely abstract, but I added "virtual void draw(Window*
const) const = 0;". I added this because upon implementation I ran into the problem of how the shapes would be able to access a method of rending to the screen.
That's reasonable. In a real graphics system you want to be able to render a
drawing on different devices - any window, a printer, a plotter etc., but
you don't want the shape object itself to be tied down to a single device.
Passing in the device to draw on is therefore a good idea.
What happens is that a Window object, w, has its "draw(Shape *)"
member called. Window::draw(Sh ape*) then passes its "this" pointer to
"Shape::draw(Wi ndow*)".
I don't think this is such a good idea. Since the Shape object is doing the
drawing, there's no need for the Window class to know about Shapes. Just
pass a reference to the Window object to the Shape's draw(), and the
overridden function in the specific shape will draw itself on the Window.
The Shape::draw member then uses the Window pointer
to access Window::put_pix el(Point, char). Window::put_pix el(Point, char)
then adds a pair<Point, char> to a vector object, which is used when
Window::show() is called. The vector is used as a sort of buffer for the
shapes to be drawn to so that multiple shapes can be drawn correctly since I am using a console mode and cout to render characters.
That all sounds good to me.
To draw something, the following would be used:

Window w(10,10);
w.draw(Dot(Poin t(5,5));
w.show();
I would have:

Window w(10,10);
Dot dot(Point(5,5)) ;
dot.draw(w);

[most code snipped]

One comment on the code: void draw(Window* const) const;
Window(const int, const int);


You can make your function parameters const if you want, but it's not usual
or necessary. Parameters are passed by value, so functions have their own
copies of them. It doesn't help the caller of a function know that a
function isn't going to modify its own copy of what's passed to it. The
caller doesn't care.

If you haven't done OO before and you are inexperienced in C++, I think
you're doing pretty well.

DW

Jul 19 '05 #2
----- Original Message -----
From: "David White" <no@email.provi ded>
Newsgroups: comp.lang.c++
Sent: Tuesday, October 21, 2003 8:40 PM
Subject: Re: How would Mr. Stroustrup implement his solution to 12.7[2]

What happens is that a Window object, w, has its "draw(Shape *)"
member called. Window::draw(Sh ape*) then passes its "this" pointer to
"Shape::draw(Wi ndow*)".
I don't think this is such a good idea. Since the Shape object is doing

the drawing, there's no need for the Window class to know about Shapes. Just
pass a reference to the Window object to the Shape's draw(), and the
overridden function in the specific shape will draw itself on the Window.
The Window class has to have a draw() member because such a member is
included in the example use of the final implementation of problem 12.7[2].
He shows that a Window, w, should be used as in the following:
w.draw(Circle(w .current(),10)) ; So, clearly, he intends for the solutions'
Window class to have a draw() member that takes a pointer to a Shape class.
I completely understand your idea, and would do it that way as well, but I
wish to complete this the way he intended it to be. One of my main
objections to my design was the addition of Shape::draw(Win dow*) because in
all the examples I have seen surrounding the Shape example, Shape only ever
has a pure virtual Shape::draw(), and that is why I felt my solution should
not be accepted. I often wondered if he mean't for the Window class to use
iterators supplied by each Shape object in order to get the Shape's shape;
that is, the character types, and position to be rendered on screen. As of
this writing, I have yet to read anything of his that had Shapes provide
iterators.

He uses examples like the following when illustrating proper design for this
example:
(src: http://technetcast.ddj.com/str0237/bs-millennium.pdf)

class Shape {
public:
virtual void draw() = 0;
virtual void rotate(double) = 0;
};

class Common { Color c; /* ... */ };

class Circle : public Shape, protected Common { /* ... */ };
As you can see, his Shape's draw() member does not take anything. This is
the difficult aspect causing me the concern with my design, as I feel that
there must be an elegant design that he had intended to be used. My adding
that Shape::draw() take a Window object was my method of solving 12.7[2],
while adhering to the requirement their be Window::draw(Sh ape&);

(Note, I mean't Shape& previously when writing Shape*).

I truly wish to understand proper OO design, and do not wish to continue my
study until I have understood what should be a very simple problem.

You can make your function parameters const if you want, but it's not usual or necessary. Parameters are passed by value, so functions have their own
copies of them. It doesn't help the caller of a function know that a
function isn't going to modify its own copy of what's passed to it. The
caller doesn't care.
Your comment is interesting. In TC++PL, Mr. Stroustrup uses non-const ints
for parameters over const ints, but I thought he was doing that for some
reason that I had not learned about yet and so was using "const int"; that
is, using const on parameters passed by value. I did this because I wanted
to make sure in my function definitions that I would not modify the original
values that were passed. I understand that changing the values would not
affect the callers, but I did it so that my use of the variables would not
alter them. If that is not a good idea, please indicate why. I wish to do
such things correctly.
If you haven't done OO before and you are inexperienced in C++, I think
you're doing pretty well.

DW


Thank you very much for your feedback, as I found it most helpful! I am
glad a more experienced person thinks I am doing alright because I have not
talked to anyone about this and so had only my own opinion of myself. Not
having anyone to communicate with in regards to C++ can be difficult at
times.
Jul 19 '05 #3
On Wed, 22 Oct 2003 01:25:48 GMT, "Oplec" <an*******@anon ymous.com> wrote:
He uses examples like the following when illustrating proper design for this
example:
(src: http://technetcast.ddj.com/str0237/bs-millennium.pdf)

class Shape {
public:
virtual void draw() = 0;
virtual void rotate(double) = 0;
};

class Common { Color c; /* ... */ };

class Circle : public Shape, protected Common { /* ... */ };
As you can see, his Shape's draw() member does not take anything. This is
the difficult aspect causing me the concern with my design, as I feel that
there must be an elegant design that he had intended to be used.
Not very elegant, but there are various solutions _given_ the interface
above -- but I don't think Bjarne meant for that to be followed to the
letter, just in spirit.

The idea of passing a drawing surface object to the 'draw' function is
probably the most elegant and natural solution. I'd pass that by reference,
not as a pointer, because a pointer can be NULL. And I'd pass that as an
abstract interface, not as a concrete 'Window', but that's just details.

If you want to avoid an argument to 'draw' you can simply hook up your
object to the drawing surface (or window, if you want). That's not very
elegant, but works. E.g., pass the drawing surface object in to the 'Circle'
or 'Line' or whatever constructor, let each object keep a reference. Or
allow for more dynamic attachment and detachment. Although that's ugly and
fraught with dangers.
My adding
that Shape::draw() take a Window object was my method of solving 12.7[2],
while adhering to the requirement their be Window::draw(Sh ape&);


It would help if you posted the text of that exercise. Not all of us have
a recent edition of TCPPPL. Mine is from 1987, I think (I did have a more
recent edition, but someone borrowed it without my knowledge...).

That said, the best advice I can give is to trust your instincts. Yes,
Bjarne is God. And no, he's not above making a small mistake here and there
(if he were then there would be no errata list...). So don't get stuck on
following the letter of the text when you should be following the spirit of the
text. Or even -- following your own ideas and logic to wherever it leads.

Hth.

Jul 19 '05 #4
Oplec <an*******@anon ymous.com> wrote in message
news:w0******** ***********@twi ster01.bloor.is .net.cable.roge rs.com...
----- Original Message -----
From: "David White" <no@email.provi ded>
Newsgroups: comp.lang.c++
Sent: Tuesday, October 21, 2003 8:40 PM
Subject: Re: How would Mr. Stroustrup implement his solution to 12.7[2]

What happens is that a Window object, w, has its "draw(Shape *)"
member called. Window::draw(Sh ape*) then passes its "this" pointer to
"Shape::draw(Wi ndow*)".
I don't think this is such a good idea. Since the Shape object is doing

the
drawing, there's no need for the Window class to know about Shapes. Just
pass a reference to the Window object to the Shape's draw(), and the
overridden function in the specific shape will draw itself on the Window.
The Window class has to have a draw() member because such a member is
included in the example use of the final implementation of problem 12.7[2]. He shows that a Window, w, should be used as in the following:
w.draw(Circle(w .current(),10)) ; So, clearly, he intends for the solutions'
Window class to have a draw() member that takes a pointer to a Shape class. I completely understand your idea, and would do it that way as well, but I
wish to complete this the way he intended it to be.
Fair enough. If that's what the exercise says...
One of my main
objections to my design was the addition of Shape::draw(Win dow*) because in all the examples I have seen surrounding the Shape example, Shape only ever has a pure virtual Shape::draw()
Yes, I've seen these as example OO designs as well, but they are usually
designs, not working implementations . I just don't think a draw() with no
parameters is right for a real graphics system. The Shape objects should be
independent of the device because it is not only possible, but highly
likely, that you will sometimes want to print whatever you've drawn on the
screen.
, and that is why I felt my solution should
not be accepted. I often wondered if he mean't for the Window class to use
iterators supplied by each Shape object in order to get the Shape's shape;
that is, the character types, and position to be rendered on screen.
Probably. I think the shapes are defined so that the n(), s() etc. members
are sufficient for the window to draw any shape. This is probably a good
enough design, or even the best design, for a system with these limitations.
Remember it is just an exercise and not necessarily a proposal for the best
design for graphics systems in general. For high resolution graphics systems
you will want to have dotted or dashed lines, thick or thin lines, curved
lines, ellipses, pear shapes, closed shapes with various kinds of shading
etc. The possibilities and complexities are endless, and in my opinion the
shape object will usually best know how to draw itself. The type of device
might make a difference too (e.g., raster or non-raster), but the shape
object is where most of the knowledge belongs. So, for this exercise
Stroustrup's design is sufficient, but for more complex drawing I don't
think it is.
As of
this writing, I have yet to read anything of his that had Shapes provide
iterators.

He uses examples like the following when illustrating proper design for this example:
(src: http://technetcast.ddj.com/str0237/bs-millennium.pdf)
That file is not accessible to me at the moment.
class Shape {
public:
virtual void draw() = 0;
virtual void rotate(double) = 0;
};

class Common { Color c; /* ... */ };

class Circle : public Shape, protected Common { /* ... */ };
As you can see, his Shape's draw() member does not take anything. This is
the difficult aspect causing me the concern with my design, as I feel that
there must be an elegant design that he had intended to be used. My adding
that Shape::draw() take a Window object was my method of solving 12.7[2],
while adhering to the requirement their be Window::draw(Sh ape&);
I assure that, in general, there's nothing wrong with adding a device
parameter to the draw function. But it isn't necessary in this exercise,
since I think it's the Window that's doing the drawing.
(Note, I mean't Shape& previously when writing Shape*).

I truly wish to understand proper OO design, and do not wish to continue my study until I have understood what should be a very simple problem.

You can make your function parameters const if you want, but it's not usual
or necessary. Parameters are passed by value, so functions have their

own copies of them. It doesn't help the caller of a function know that a
function isn't going to modify its own copy of what's passed to it. The
caller doesn't care.


Your comment is interesting. In TC++PL, Mr. Stroustrup uses non-const ints
for parameters over const ints, but I thought he was doing that for some
reason that I had not learned about yet and so was using "const int"; that
is, using const on parameters passed by value.


No, I think he's using non-const parameters because there's no need to make
them const and because it's the convention.
I did this because I wanted
to make sure in my function definitions that I would not modify the original values that were passed. I understand that changing the values would not
affect the callers, but I did it so that my use of the variables would not
alter them.
Usually, programmers don't accidentally change the passed parameters. And
even if they do it won't affect anything outside the function. So, most
people don't bother making the parameters const.
If that is not a good idea, please indicate why. I wish to do
such things correctly.


My problem with it is mainly that the callers see the interface. For
example:

void f(const char * const p);

Here, the first const is important for the caller, but the second const is
only important for the function. I think it's better if function interfaces
are not cluttered with information not relevant to the caller. However,
others might disagree.

DW

Jul 19 '05 #5

"Oplec" <an*******@anon ymous.com> wrote in message
news:w0******** ***********@twi ster01.bloor.is .net.cable.roge rs.com...
You can make your function parameters const if you want, but it's not usual
or necessary. Parameters are passed by value, so functions have their own copies of them. It doesn't help the caller of a function know that a
function isn't going to modify its own copy of what's passed to it. The
caller doesn't care.


Your comment is interesting. In TC++PL, Mr. Stroustrup uses non-const ints
for parameters over const ints, but I thought he was doing that for some
reason that I had not learned about yet and so was using "const int"; that
is, using const on parameters passed by value. I did this because I wanted
to make sure in my function definitions that I would not modify the

original values that were passed. I understand that changing the values would not
affect the callers, but I did it so that my use of the variables would not
alter them. If that is not a good idea, please indicate why. I wish to do
such things correctly.


Since you explain it that way, your technique is valid. Nonetheless,
programmers very rarely code this way. Some programmers have never seen it,
and for some reason it looks so odd to them that they might think it's a
bug, or at least go off in search of the answer. Therefore, from a
maintenance perspective, it might be considered "confusing" . But a
programmer's misunderstandin g of a properly working language feature doesn't
mean you shouldn't use it. There's nothing wrong with it. You might want
to make a comment as to your intent, if others read your code.
Jul 19 '05 #6

"David White" <no@email.provi ded> wrote in message
news:Nl******** **********@nasa l.pacific.net.a u...

Here, the first const is important for the caller, but the second const is
only important for the function. I think it's better if function interfaces are not cluttered with information not relevant to the caller. However,
others might disagree.


In theory, I definitely agree. In practice, there are certain things that
the language requires that force your hand. For example, when declaring
your function, you don't need to put the parameter names, just the types.
This is good - technically, it exposes a tiny part of the implementation.
(Of course, you might at least want to make a comment as to what the
parameter is for if it's not obvious.

void f(int, int); // fine
void f(int length) // fine - nice feature of C++
{...}

Unfortunately, you can't do this. This would also help hide some of the
implementation (you are using the const parameter as an implementation tool
only), but the language doesn't allow it.

void f(int);
void f(const int length)
{...}

So if you want to do this, it *has* to go in the declaration and the user
will have to see it.
Jul 19 '05 #7

"Oplec" <an*******@anon ymous.com> wrote in message
news:FM******** ***********@twi ster01.bloor.is .net.cable.roge rs.com...
Hi,

I am learning standard C++ as a hobby. The C++ Programming Language :
Special Edition has been the principal source for my information. I read the entirety of the book and concluded that I had done myself a disservice by
having not attempted and completed the exercises. I intend to rectify that.
My current routine is to read a chapter and then attempt every exercise
problem, and I find that this process is leading to a greater understanding of the language and implementation.

However, occasionly I am unable to complete some of the exercises, or am not satisfied with my method of solution. One such exercise is 12.7[2].

From what I read in the chapter and a few papers of his, Mr. Stroustrup
suggests that most of the time the best implemention for the Shape, Dot,
Line, Rectangle hierarchy would be for Shape to be a purely abstract base
class, and for Dot, Line, Rectangle to inheirit from Shape and implement the virtual functions. In his code examples he routinely defines "virtual void
draw() = 0" as a member of the Shape class. Upon implementing a solution to 12.7[2] I experienced a difficulty surrounding how to implement the drawing of Shapes for the Window class that must exist. My implementation was for
simple console mode character output using std::cout.

Since I am new to OO programming, I feel that I lack some understanding of
what he intended my solution to be similar to.


If you still have questions, why don't you ask him personally? You would
want to distill the message down to be as succinct as possible because I'm
sure he's very busy. He has helped me when I couldn't find a complete
answer here, and in your case you're asking something directly related to
his book.
Jul 19 '05 #8
"Alf P. Steinbach" <al***@start.no > wrote in message
news:3f******** ********@News.C IS.DFN.DE...
It would help if you posted the text of that exercise. Not all of us have
a recent edition of TCPPPL. Mine is from 1987, I think (I did have a more
recent edition, but someone borrowed it without my knowledge...).


Hello,

I would copy 12.7[2] from the book and reproduce it here, but all such
rights are reserved by the publisher. However, I will do my best to
represent the idea.

Write a simple graphics system, and if you don't have access to a proper
graphics system you may use an ASCII implementation. In that implementation,
points are represented by a character position and you write a suitable
character to the screen. A Window class has a constructor Window(i,j), where
i is the width, and j the height, of an area on the screen. Points use
Cartesian coordinates. A Point is represented as a coordinate pair,
Point(x,y), but a Point is not a Shape. Window has the member
Window::current () that returns the current position. Default position for
Window is Point(0,0). w.current(p) can be used to set the current position,
where p is a Point. A line is represented by two Points, for example
Line(w.current( ),p7); There is a Shape class that is the base interface for
all drawable shapes such as Lines, Dots, Rectangles, Circles. The Dot shape
is used to represent a Point that is to be drawn. All Shapes are invisible
until they are draw()n. Usage: w.draw(Line(w.c urrent(), 20)); All the shapes
have 9 points of contact: n (north), e(east), s (south), w (west), ne
(north-east), nw (north-west), se (south-east), sw (south-west), and c
(center). After a shape is drawn, w.current() equals the shape's se().
Usage: Line(x.s(), y.c());, which will create a Line from x's south point to
y's center point. A Rectangle is created Rectangle(p1, p2), where p1 is the
rectangle's bottom left point, and p2 is its top right. Usage:
Rectangle(Point (20,20), w.current()); To demonstrate the working of your
solution, render a child's drawing of a house, that is, a roof, two windows,
the body, and a door.

The following is my understanding of the previous paragraph:
What that all means is that there should ast least be an abstract base class
named Shape that contains the virtual members n(), e(), s(), w(), ne(),
nw(), se(), sw(), c(). He did not specify a Shape::draw(), but he used such
a member in an example in the book.

The Point class simply holds Cartesian coordinates.

A Dot derived from Shape and is simply a Shape having a single Point and
represented as a single character position on the screen.

The Line is derived from Shape and is created by supplying two Points, and
drawn as a series of characters between and including those positions. I had
to work out a method to actually draw lines, and then discovered that there
is a Bressenham algorithm for doing this. It would have saved me much paper
figuring it out myself.

The Window class is created by supplying two coordinates, but I do not
believe those to be Points, but rather ints. I could be mistaken. It has a
current() member that returns the current Point, that is the last shape's
se() or Point(0,0). A current(Point) member that sets the current position.
And a draw(Shape&) that draws a shape, and is at the heart of my objection,
concern over my implementation.

That constitutes what I know for certain of the problem. My translation of
12.7[2] is in keeping with its idea while not violating the copyright.

Please let me know how you would solve this problem, knowing that I can only
use the ASCII reprentation for the graphics. Any ideas are most welcome.

Thank you for time, Oplec.
Jul 19 '05 #9
"David White" <no@email.provi ded> wrote in message
news:Nl******** **********@nasa l.pacific.net.a u...
Yes, I've seen these as example OO designs as well, but they are usually
designs, not working implementations . I just don't think a draw() with no
parameters is right for a real graphics system. The Shape objects should be independent of the device because it is not only possible, but highly
likely, that you will sometimes want to print whatever you've drawn on the
screen.
If I had were to have free reign over the design, I would most likely
implement a Surface class that Shapes draw to. My only question would then
be whether or not such a Surface should provide the members for drawing to
it, such as put_pixel(), or whether another class should be implemented to
do so. Any ideas?
Probably. I think the shapes are defined so that the n(), s() etc. members
are sufficient for the window to draw any shape. This is probably a good
enough design, or even the best design, for a system with these limitations. Remember it is just an exercise and not necessarily a proposal for the best design for graphics systems in general. For high resolution graphics systems you will want to have dotted or dashed lines, thick or thin lines, curved
lines, ellipses, pear shapes, closed shapes with various kinds of shading
etc. The possibilities and complexities are endless, and in my opinion the
shape object will usually best know how to draw itself. The type of device
might make a difference too (e.g., raster or non-raster), but the shape
object is where most of the knowledge belongs. So, for this exercise
Stroustrup's design is sufficient, but for more complex drawing I don't
think it is.
From my understanding of the problem, and how I implemented it, the
Points returned by the n(), e(), ..., members could not be used to draw a
shape unless Window knew of what shape the object being drawn was, such as
Line. That would violate the whole idea of what Mr. Stroustrup wrote in the
chapter; He seems to detest casts.
No, I think he's using non-const parameters because there's no need to make them const and because it's the convention.


If it is the convention then I will follow it. Thank you for informing
me of this matter since I was not expecting any help on my code, but it is
most welcome.

Thank you for your time, Oplec.
Jul 19 '05 #10

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

Similar topics

7
2343
by: arnuld | last post by:
problem: define functions F(char), g(char&) & h(const char&). call them with arguments 'a', 49, 3300, c, uc & sc where c is a char, uc is unsigned char & sc is signed char. whihc calls are legal? which calls cause the compiler to to introduce a temporary variable? solution: this is the code ----------------------------------------------------------- #include <iostream> void f(char) {};
5
1762
by: arnuld | last post by:
------------- PROGRAMME ----------- /* Stroustrup, 5.9, exercise 2 STATEMENT: what on your system, ar ethe restrictions on the types char*, int* and voic*? e.g. may an int* have an odd value? HINT: alignment SOLUTION:
11
1466
by: arnuld | last post by:
this programme compiles but runs into some strange results, a semantic- BUG is there. i even put some "std::cout" to know what is wrong but it does something that i did NOT order it to do: --------------- PROGRAMME ------------------- /* Stroustrup, 5.9 exercise 4 STATEMENT: write a programme that swaps 2 integers. solve it using 1st with pointers and then references.
6
3036
by: arnuld | last post by:
this one was much easier and works fine. as usual, i put code here for any further comments/views/advice: --------- PROGRAMME ------------ /* Stroustrup: 5.9 exercise 7 STATEMENTS: Define a table of the name sof months o fyear and the number of days in each month. write out that table. Do this twice:
5
1756
by: arnuld | last post by:
this works fine, any advice for improvement: ------------- PROGRAMME ------------------ /* Stroustrup, 5.9, exercise 10 STATAMENT: define an array of strings,where strings contains the names months .. Print those strings. Pass the array to a function that prints those strings.
13
2219
by: arnuld | last post by:
this does not work, i know there is some problem in the "for loop" of "print_arr" function. i am not able to correct the weired results i am getting. i have no compile time error, it is only semantic-bug that is causing the trouble: EXPECTED: january, february, march....december GOT: january, january, january.........january ------------- PROGRAMME -------------- /* Stroustrup, 5.9, exercise 10
14
2462
by: arnuld | last post by:
there is no "compile-time error". after i enter input and hit ENTER i get a run-time error. here is the code: ---------- PROGRAMME -------------- /* Stroustrup, 5.9, exercise 11 STATEMENT: Read a sequence of words from the input. use "quit" as the word
20
2146
by: gremlin | last post by:
http://www.cilk.com/multicore-blog/bid/6703/C-Inventor-Bjarne-Stroustrup-answers-the-Multicore-Proust-Questionnaire
1
3514
by: blangela | last post by:
Bjarne Stroustrup has a new text coming out called "Programming: Principles and Practice Using C++" (ISBN: 0321543726), due to be published in December of this year. Some of the features of this new text include: *Its history: The text was developed in the author's introductory programming course at Texas A&M and has been used successfully by hundreds of students.
0
7977
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
7894
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 synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8276
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. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
6705
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 launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
5847
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5437
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 into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3893
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 the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
1496
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1245
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.