FLTK C++ Fl_line 不画

FLTK C++ Fl_line don't draw

我的任务是调试一个代码,该代码旨在使用 FLTK 从 4 个点中绘制一个简单的多边形。 MyWindow class 派生自 Fl_WindowShape class 是 ClosedPolyline 的父 class。 MyWindowShape 都持有一个矢量来绘制所有形状。

问题是在编译和运行之后,win.show()打开一个空的window,没有任何绘图。我对这种行为感到困惑。

代码如下(我省略了一些与绘图无关的部分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());
}

让我们看看您的 MyWindow::Attach 函数:

void Attach(Shape s) {
shapes.push_back(&s);
}

在函数中,参数s是按值传递的。这意味着它与函数内部的 局部变量 相同。因此它将超出范围并在函数 return.

后被破坏

保存指向该变量的指针将导致您保存一个杂散指针,指向一个不存在的对象。取消引用该指针将导致 undefined behavior,使您的整个程序变得 格式错误 和无效。

解决问题的一种方法是确保对象不超出范围。这可以通过使用 智能指针 来完成,例如std::unique_ptr。并在 main 函数中定义变量 p 时从一开始就使用它。


另一种解决问题的方法是假设传递给 AttachShape 的生命周期比 Shape 对象长,因此您可以传递 Shape 参考:

void Attach(Shape& s) {
    shapes.push_back(&s);
}

现在您不再获取 Shape 对象的副本,并将指针推送到原始对象(在您的例子中是 main 函数中的对象 p)。只要原始对象处于活动状态且在范围内,取消引用指针就是有效的。

我在 VS2015 中尝试 运行 该代码并得到很多错误(当然修复附加 window 通过引用传递)但是当我 运行 linux 时,它可以画画,所以我认为你应该移动到 linux。