The problem is that you can't make a vector <Rectangle> because Rectangle is
derived from Shape and Shape hides the copy constructor as well as the
assignment operator,
class Shape
{
//...
private:
Shape(const Shape&); // prevent copying
Shape& operator=(const Shape&);
};
Both of these are requirements for a vector. OK, so the STL details haven't
been covered yet...but, we have been given vector already and encouraged to
use it...and this library is given "as is" so shouldn't it work for vector?
A vector <Rectangle> seems pretty basic, right?
OK, now given the explicit comment that copying is blocked, and therefore
vector use is preccluded for the Rectangle/Shape class object, what should
the reader do? If you examine the Shape class you will find a vector
<Point> so one way is to build your rectangles up with bunches of vector
<Point> declarations. But then what purpose do the GUI library classes
serve?
The second bother is that the GUI/FLTK library use references to application
objects. The Window::attach function uses a reference to a object which
means the object must persist in the application and not be temporary. This
tends to lead to global variables, lots of preallocation of variables that
must be "fixed up" at run time when the details are known, arrays etc. The
following doesn't work,
void make_rectangles(Simple_window& win, const vector <Point>& origins)
{
for (size_t i = 0; i < origins.size(); ++i) {
Rectangle rect(origins[i], RECT_WIDTH, RECT_HEIGHT);
win.attach(rect);
}
}
Because the rectangles are temporary objects and the library uses references
to objects, this crashes on the next display update. So the only way to use
such a function is to
A. pass in preset Rectangles (but don't use a vector!)
B. use a global variable of rectangles (also not a vector)
C. make a class with a non vector collection of Rectangles
This is the obviously wrong path! Other solutions involve a slew of hard
coded Rectangles that are fairly resistant to any kind of maintenance or
functions or algorithms.
I thought the intent was to explore the usefulness of the GUI interface
library rather than struggle trying to overcome its limitations. Exercises 5
and 10 are becoming tedious chores.
Lastly, I may be missing an obvious solution to this problem.
Any hints?
- tim
#include <vector>
#include <iostream>
#include <sstream>
using namespace std;
class Shape{
public:
Shape(int points=0)
:points(points){
}
int getPoints() const{
return points;
}
void setPoints(int points){
this->points = points;
}
private:
Shape(const Shape& s){
this->points = s.points;
}
Shape& operator=(const Shape& s){
this->points = s.points;
return *this;
}
int points;
};
class Rect: public Shape{
public:
Rect(int points=1, int size=1)
:Shape(points), size(size){
}
Rect(const Rect& r){
this->size=r.size;
setPoints(r.getPoints());
}
Rect& operator=(const Rect & r){
this->size=r.size;
setPoints(r.getPoints());
return *this;
}
string toString(){
stringstream s;
s << "Points: " << getPoints()<< " Size: " << size ;
return s.str();
}
private:
int size;
};
Rect makeRect(int a, int b){
Rect r(a,b);
//calling copy constructor
return r;
}
void print(Rect r/*calling copy constructor*/){
cout << r.toString() << endl;
}
int main(){
vector<Rect> rects;
rects.push_back(makeRect(1,2));
rects.push_back(makeRect(3,4));
Rect h=makeRect(5,6); //calling copy constructor
rects.push_back(h);
for(Rect r: rects){
print(r);
}
}
2012/4/18 tfmccarthy_verizon_mail <tfmcc...@verizon.net>:
> --
> You received this message because you are subscribed to the Google Groups "PPP-public" group.
> To post to this group, send email to ppp-p...@googlegroups.com.
> To unsubscribe from this group, send email to ppp-public+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/ppp-public?hl=en.
>
Any hints?
- tim
--
You received this message because you are subscribed to the Google Groups "PPP-public" group.
To post to this group, send email to ppp-p...@googlegroups.com.
To unsubscribe from this group, send email to ppp-public+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/ppp-public?hl=en.
________________________________
This e-mail and any attachments are intended for the use of the person or entity to which it is addressed and may contain information that is privileged, confidential, and exempt from disclosure under applicable law. If you have received this electronic transmission in error, please delete it from your system without copying, distributing, or disseminating it in any way, and notify the sender by reply email.
What I am saying is that the library you are given to compensate for this is
is the GUI interface library. That library has a private copy constructor
that should prevent the reader from using a Rectangle the template argument
to vector.
So the question is, how did people do the exercises (specifically 5, and 10)
using the GUI library as provided? Not impossible to do but very, very,
messy. It seems to me that it should have raised a big stink.
If you are expected to create your own library then what is the GUI library
for? An example?!?
- tim
I think a reader should have serious problems completing the exercises (if
at all) without information from a subsequent chapter.
> In chapter 13, the recommendation is to use vector_ref<Rectangle> instead.
> This is a vector of pointers and you are to use "new" to make a new
> rectangle. Check out pages 459 - 461
>
First is Exercise 12.4 - the checker board.
OK, here's one way to solve this:
const int MAX_ROW = 8;
const int MAX_COL = 8;
const int x_incr = screen_width/10;
const int y_incr = screen_height/10;
// This next declaration is unplesant.
// n.b vector <Rectangle> won't work due to private copy ctor
Rectangle squares[MAX_ROW * MAX_COL] =
{
Rectangle(Point(x_incr, y_incr), x_incr, y_incr)
, Rectangle(Point(x_incr, y_incr), x_incr, y_incr)
, Rectangle(Point(x_incr, y_incr), x_incr, y_incr)
, Rectangle(Point(x_incr, y_incr), x_incr, y_incr)
, Rectangle(Point(x_incr, y_incr), x_incr, y_incr)
, Rectangle(Point(x_incr, y_incr), x_incr, y_incr)
, Rectangle(Point(x_incr, y_incr), x_incr, y_incr)
, Rectangle(Point(x_incr, y_incr), x_incr, y_incr)
//... and so on
};
Messy and unattrictive and uses array initialization that many programmers
have trouble with but I now have an array of Rectangles that I can
manipulate,
// reposition each rectangle to the board
// alternating red and white squares
int idx = 0;
for (int row = 0; row < MAX_ROW; ++idx, ++row) {
for (int col = 0; col < MAX_COL; ++idx, ++col) {
squares[(row * MAX_ROW) + col].move(row * x_incr, col * y_incr);
squares[(row * MAX_ROW) + col].set_fill_color((idx % 2) ? Color::red :
Color::white);
win.attach(squares[(row * MAX_ROW) + col]);
}
}
Very fragile and difficult to maintain. This uses arrays insetad of vectors
with hard coded initialization values and a loop to reintiialize values.
There are reasons to use arrays but this isn't one of them (IMHO). Said
another way, this isn't a very convincing argument for using arrays rather
than vectors.
Next comes Exercise 12.10 - details in separate post
- tim
On Apr 19, 2012, at 6:14 PM, tfmccarthy_verizon_mail wrote:
> First is Exercise 12.4 - the checker board ...
I asked Bjarne how he expected people to solve this, without knowledge of the Chapter 13 material. I think he's come to the conclusion that this exercise really doesn't belong here, because there aren't any non-ugly solutions.
Art Werschulz (8-{)} "Metaphors be with you." -- bumper sticker
GCS/M (GAT): d? -p+ c++ l u+(-) e--- m* s n+ h f g+ w+ t++ r- y?
Internet: agw STRUDEL comcast.net
// This is exercise 10 code from "Chapter 12 A Display Model" of
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
// 10. Draw the file diagram from �12.8.
//
//
// There are boxes for:
//
// FLTK Headers
// FLTK code
// Point.h
// Window.h
// GUI.h
// Graph.h
// Simple_window.h
// Graph.cpp
// Window.cpp
// GUI.cpp
// chapter12.cpp
//
#include "Simple_window.h" // if we want that "Next" button
#include "Graph.h"
#include "std_lib_facilities.h"
#include <iostream>
using namespace Graph_lib;
// file_rectangle
// This class is a replacement for the Rectangle class that
// overcomes the copy limitiation of the Graph_lib::Rectangle
// class. The class provides
//
// - a default constructor
// - a copy constructor
// - an assignment operator
//
// that allow the class to be used with a STL vector.
//
// A custom constructor is provided to simplfy initialization.
//
// Finally, the class provides a customn virtual draw_lines
// function to add the additional display features that are
// the attributes of the class
//
// CAVEAT:
// There is a significant flaw with this class.
// Can you spot it?
//
// Hint: A class should be consistent.
//
struct file_rectangle : Rectangle
{
// attributes
string file_name; // a file name
string file_description; // a file description
vector <string> file_parent; // the parent file (if any)
// default constructor
file_rectangle()
: Rectangle(Point(0,0), 1, 1)
{
set_color(Color::black);
set_fill_color(Color::yellow);
}
// custom constructor
file_rectangle(const Rectangle& r, const string& name, const string&
description, const string& parent)
: Rectangle(r.point(0), r.width(), r.height())
, file_name(name)
, file_description(description)
{
set_color(Color::black);
set_fill_color(Color::yellow);
file_parent.push_back(parent);
}
// copy constructor
file_rectangle(const file_rectangle& rhs)
: Rectangle(rhs.point(0), rhs.width(), rhs.height())
{
*this = rhs;
}
// assignment operator
file_rectangle& operator=(const file_rectangle& rhs)
{
if (this == &rhs) {
return *this;
}
file_name = rhs.file_name;
file_description = rhs.file_description;
for (size_t i = 0; i < rhs.number_of_points(); ++i) {
set_point(i, rhs.point(i));
}
set_color(rhs.color());
set_fill_color(rhs.fill_color());
set_style(rhs.style());
return *this;
}
// override virtual function
void draw_lines() const
{
Rectangle::draw_lines(); // base class draw
// now draw name, description
Text name_txt(point(0), file_name);
name_txt.set_color(Color::black);
name_txt.set_font(Font::courier_bold);
name_txt.set_font_size(18);
name_txt.draw_lines();
// now draw description
Point pt(point(0));
pt.y += height()/2;
Text descr_txt(pt, file_description);
descr_txt.set_color(Color::black);
descr_txt.set_font(Font::courier);
descr_txt.set_font_size(14);
descr_txt.draw_lines();
// TBD: multiple line description support
}
};
//------------------------------------------------------------------------------
int main ()
try
{
const int rect_height = 30;
const int rect_width = 175;
const int screen_width = 4 * rect_width;
const int screen_height = 400;
const int screen_origin_xpos = 100;
const int screen_origin_ypos = 100;
string title("Exercise 10");
Point topleft(screen_origin_xpos, screen_origin_ypos);
Simple_window win(topleft, screen_width, screen_height, title);
// the file diagram as a vector representing a graph relationship.
vector <file_rectangle> file_graph;
// messay hardcoded initialization
// n.b. multiple warnings : "conversion from 'double' to 'int', possible
loss of data"
file_graph.push_back(file_rectangle(Rectangle(Point(2 * rect_width, 0),
rect_width, rect_height), "", "FLTK_Headers", ""));
file_graph.push_back(file_rectangle(Rectangle(Point(3 * rect_width, 1.5 *
rect_height), rect_width, rect_height), "", "FLTK code", ""));
file_graph.push_back(file_rectangle(Rectangle(Point(0.5 * rect_width, 1.5 *
rect_height), rect_width, rect_height), "Point.h", "", ""));
file_graph.push_back(file_rectangle(Rectangle(Point(2 * rect_width, 3 *
rect_height), rect_width, rect_height), "Window.h", "", ""));
file_graph.push_back(file_rectangle(Rectangle(Point(1.2 * rect_width, 4.5 *
rect_height), rect_width, rect_height), "Window.cpp", "", "Window.h"));
file_graph.push_back(file_rectangle(Rectangle(Point(1.5 * rect_width, 8 *
rect_height), rect_width, rect_height), "Simple_window.h", "", ""));
file_graph.push_back(file_rectangle(Rectangle(Point(2.5 * rect_width, 6 *
rect_height), rect_width, rect_height), "GUI.h", "", ""));
file_graph.push_back(file_rectangle(Rectangle(Point(3 * rect_width, 8 *
rect_height), rect_width, rect_height), "GUI.cpp", "", "GUI.h"));
file_graph.push_back(file_rectangle(Rectangle(Point(0.5 * rect_width, 6 *
rect_height), rect_width, rect_height), "Graph.h", "", ""));
file_graph.push_back(file_rectangle(Rectangle(Point(0, 8 * rect_height),
rect_width, rect_height), "Graph.cpp", "", "Graph.h"));
file_graph.push_back(file_rectangle(Rectangle(Point(rect_width, 10 *
rect_height), rect_width, rect_height), "chapter12.cpp", "", "Graph.h"));
// load objects into window
for (size_t i = 0; i < file_graph.size(); ++i) {
win.attach(file_graph[i]);
}
// TBD: draw arrows for each element that has a parent
// Serch the vector (i.e. find)) for the parent by
// parent name. Then, draw a line from child element
// (arbitrary point on child rect) to the parent
// (arbitrary point on parent rect) and add arrowhead.
//
win.wait_for_button(); // Display!
}
catch(exception& e) {
// some error reporting
cerr << "Opps! error " << e.what() << endl;
return 1;
}
catch(...) {
// some more error reporting
cerr << "Opps! Something bad happened" << endl;
return 2;
}
//------------------------------------------------------------------------------
Once I reached this point in the exercise that I stopped and said, "Enough!"
This is too much to expect from CS 101...though I still think the expression
parser is more demanding. But that application was developed over a few
chapters and lectures with many side trips and experimental journeys. This
is just one exercise. What does this entail?
Class derivation.
The problem with the Rectangle class must be recognized and analysed to
determine why it can't be used in a vector.This involves understanding why a
vector needs the copy constructor and assignment operator. Understanding
that concept is a _major_ achievement for the course. If you understand that
then the rest of the STL containers and algorithms will fall in line.
The next step is to decide if you derive from an existing class or proivde
a new one. Should you create a new Rectangle or a new Shape that acts a lot
like a Rectangle? This is derivation ("IS-A") or composition ("HAS-A"). Then
implementation detail for copy constructor and assignment operator and
finally, why and how to override draw_lines() to get the new behavior. Note
that here I used derviation for the new class in order to explore the
Graph_lib classes in some detail (this is an effective way to dig into a set
of classes) but there is a flaw here. the Rectangle width and height are not
accurate.They reflect the initialization values for the base class and are
non-modifiable. (BTW: you can't have a zero sized Rectangle. Who knew?)
Now all of this material has, been presented or made available, I believe.
But not in a unified manner. That is what these sections of the text are
about and this is the first chapter!. So I think we have the cart in front
of the horse here!
Once the class has been defiined the rest of the program is initialization
and actication...with one significant exception. The parent-child lines
between the files is not implemented. I've outlined the idea of it in the
comments and with a bit more effort I think it can be done reasonably well.
But I had alreay thrown in my towel so I will leave it at that.
I was expecting the exercises to encourage the reader to experiment with the
capabilities of the library classes to see what they can do, do well, and
how they fit together for a display. this seemed to be the opposite of that.
IMHO
YMMV
- tim