我的任务是调试一个代码,该代码用于使用FLTK从4个点中绘制一个简单的多边形。 MyWindow
类派生自Fl_Window
。 Shape
类是ClosedPolyline
的父类。 MyWindow
和Shape
都有一个向量来绘制所有形状。
问题是编译并运行后,win.show()
会打开一个没有任何绘图的空窗口。我很难理解这种行为。
以下是代码(我省略了一些与绘图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;
};
这是main()
函数:
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());
}
答案 0 :(得分:2)
让我们来看看你的MyWindow::Attach
功能:
void Attach(Shape s) {
shapes.push_back(&s);
}
在函数中,参数s
按值传递。这意味着它与函数内的局部变量相同。因此,一旦函数返回,它将超出范围并被破坏。
保存指向该变量的指针将导致您保存指向不存在的对象的杂散指针。取消引用该指针将导致undefined behavior,导致整个程序格式错误并无效。
解决问题的一种方法是确保对象不会超出范围。这可以通过使用智能指针来完成,例如std::unique_ptr
。并且在p
函数中定义变量main
时已经从头开始使用它。
解决问题的另一种方法是假设传递给Shape
的{{1}}的生命周期比Attach
对象更长,因此您可以传递Shape
} 通过引用:
Shape
现在您不再获取void Attach(Shape& s) {
shapes.push_back(&s);
}
对象的副本,并将指针推送到原始对象(在您的情况下是Shape
函数中的对象p
)。只要原始对象处于活动状态并且在范围内,解除引用指针就会有效。
答案 1 :(得分:0)
我尝试在VS2015中运行该代码并获得大量错误(当然通过引用修复附加窗口传递)但是当我运行到linux时,它可以绘制,所以我认为你应该转移到linux。