Reputation: 5
I was tasked to debug a code that was meant to draw a simple polygon out of 4 points using FLTK. The MyWindow
class derive from Fl_Window
. The Shape
class is the parent class for ClosedPolyline
. Both MyWindow
and Shape
hold a vector to draw all of the shapes.
The problem is that after compiling and run, win.show()
opens an empty window without any drawing. I'm puzzled to understand this behavior.
Here is the code (I've omitted some of the parts that are not related to drawing ClosedPolyline
):
#include <iostream>
#include <FL/Fl.H>
#include <FL/Fl_Draw.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Device.H>
#include <initializer_list>
#include <vector>
#include <functional>
//#include <cmath>
//#include <math.h>
struct Point {
int x,y;
Point(int xx, int yy) : x(xx), y(yy) { }
};
class Shape{
public:
Point point(int idx) const {
return (points[idx]);
}
unsigned int points_size() const {
return points.size();}
void draw() /*const*/{
draw_lines();
}
void add(Point p){ points.push_back(p); }
protected:
virtual void draw_lines() {}
private:
std::vector<Point> points;
};
class ClosedPolyline: public Shape {
public:
/*ClosedPolyline(std::initializer_list<Point> pp) {
if (pp.size() > 0) {
for (Point p: pp)
add(p);
}
}
*/
ClosedPolyline(Point a1, Point a2, Point a3, Point a4){
add(a1); add(a2); add(a3); add(a4);
}
protected:
void draw_lines() override{
for (unsigned int i=1; i<points_size(); ++i){
fl_line(point(i-1).x, point(i-1).y, point(i).x, point(i).y);
}
}
};
class MyWindow: public Fl_Window {
public:
MyWindow(int x, int y, int w, int h, const char* title = 0)
: Fl_Window(x, y, w, h, title) {}
void Attach(Shape s) {
shapes.push_back(&s);
}
//void draw_shapes(){draw();}
protected:
void draw() override{
for(Shape * s: shapes) {
s->draw();
//s.draw();
}
}
private:
std::vector<Shape*> shapes;
};
And here is the main()
function:
int main() {
MyWindow win(100, 100, 600, 400, "C++ Test task");
ClosedPolyline p{Point{100, 100}, Point{100, 200}, Point{500, 100}, Point{500, 200}};
win.Attach(p);
win.end();
win.show();
return (Fl::run());
}
Upvotes: 0
Views: 1081
Reputation: 11
I try run that code in VS2015 and get a lot of error( of course fix attach window pass by reference ) But when I run to linux , it can draw, So I think you should move to linux.
Upvotes: 0
Reputation: 409196
Lets take a look at your MyWindow::Attach
function:
void Attach(Shape s) {
shapes.push_back(&s);
}
In the function, the argument s
is passed by value. That means it's the same as a local variable inside the function. And as such it will go out of scope and be destructed once the function return.
Saving a pointer to that variable will lead to you saving a stray pointer, pointing to a non-existing object. Dereferencing that pointer will lead to undefined behavior, turning your whole program ill-formed and invalid.
One way to solve the problem is to make sure that the object don't go out of scope. This can be done by using smart pointers like e.g. std::unique_ptr
. And to use it from the beginning already when you define the variable p
in the main
function.
Another way to solve your problem is to assume that the Shape
passed to Attach
will have a lifetime that outlives the Shape
object, and you could therefore pass the Shape
by reference:
void Attach(Shape& s) {
shapes.push_back(&s);
}
Now you no longer get a copy of the Shape
object, and push a pointer to the original object (in your case the object p
in the main
function). Dereferencing the pointer will be valid as long as the original object is alive and in scope.
Upvotes: 2