我把整个代码放在github上:https://github.com/marianatuma/CG
我有一个名为 point 的结构,用 line.h
声明,以及一条类线,它有两个点,开始和结束。编辑:我之前没有添加它,但Line继承自GraphObj。 graphObj.h
:
class GraphObj {
private:
type t;
std::string name;
public:
GraphObj(type t, std::string name);
type getType();
std::string getName();
};
line.h
:
#ifndef LINE_H
#define LINE_H
struct point {
double x;
double y;
};
class Line {
private:
point start;
point end;
public:
Line(type t, std::string name) : GraphObj(t, name) {};
void setStart(double x, double y);
void setEnd(double x, double y);
point getStart();
point getEnd();
};
#endif
line.cpp
:
#include "line.h"
void Line::setStart(double x, double y) {
this->start.x = x;
this->start.y = y;
}
void Line::setEnd(double x, double y) {
this->end.x = x;
this->end.y = y;
}
point Line::getStart() {
return start;
}
point Line::getEnd() {
return end;
}
当我尝试访问这些点中的任何一个时,我总是遇到分段错误。我试着把它们公开,但没有用。我也尝试使用吸气剂,但它也没有用。以下是我初始化它们的方式:
该线位于称为显示文件的线列表中,将与 cairo 一起使用以绘制它们。
displayFile.h
:
#ifndef DISPLAYFILE_H
#define DISPLAYFILE_H
#include <list>
#include "graphObj.h"
class DisplayFile {
private:
std::list<GraphObj*>* objectList;
std::list<GraphObj*>::iterator it;
int size;
public:
DisplayFile();
void add(GraphObj* g);
GraphObj* getNextObject();
void resetIterator();
int getSize();
};
#endif
displayFile.cpp
:
#include "displayFile.h"
DisplayFile::DisplayFile() {
this->objectList = new std::list<GraphObj*>();
this->it = objectList->begin();
this->size = 0;
}
void DisplayFile::add(GraphObj* g) {
std::list<GraphObj*>::iterator tempIt;
tempIt = objectList->begin();
this->objectList->insert(tempIt, g);
this->size++;
}
GraphObj* DisplayFile::getNextObject() {
return *++it;
}
void DisplayFile::resetIterator() {
it = objectList->begin();
}
int DisplayFile::getSize() {
return size;
}
DisplayFile 返回一个 GraphObj 而不是 objectList,所以它必须自己遍历 objectList,因此需要 resetIterator(所以当主代码遍历列表时,它会将迭代器重置到列表的开头,但到目前为止我还没有在任何地方调用此方法(。main.cpp
中使用 Line 实例的代码如下:
static void do_drawing(cairo_t *cr)
{
/* not using these right now
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 0.5);
*/
int size = df->getSize(); //df is the list
for(int i = 0; i < size; i++) {
Line* g = df->getNextObject();
point start = g->getStart();
}
}
问题仅在我尝试访问点时开始,我可以毫无问题地从该线实例访问其他属性。我做错了什么?
编辑:我希望我提供了足够的信息,主代码很长,与行类没有太大关系,所以我认为它无关紧要。
问题出在您的列表类上。
class DisplayFile {
private:
std::list<GraphObj*>* objectList; // Why not just a list<GraphObj*>
std::list<GraphObj*>::iterator it; // Why use this?
int size; // WHY manually keep track of a STL container size?
public:
DisplayFile();
void add(GraphObj* g);
void resetIterator();
int getSize();
};
在实现文件中:
GraphObj* DisplayFile::getNextObject() {
return *++it;
}
正如我已经评论过的:这是赢家...想一想,如果it
已经碰巧是列表中的最后一个元素,并且您要求getNextObject()
怎么办?繁荣
我不明白为什么你不能用一个漂亮而简单的std::list
替换整个DisplayFile
类:
std::list<GraphObj*> objectList;
// I would also advice to change to smart pointers here
// for example: std::list<std::shared_ptr<GraphObj> > objectList;
// or std::list<std::unique_ptr<GraphObj> > objectList;
然后,您只需使用 STL 方法处理列表:
在前面添加一个项目:(为了简单起见,让我们假设GraphObj
有一个默认构造函数(
GraphObj* g = new GraphObj();
objectList.push_front(g);
// If you change to smart pointers:
// objectList.push_front(std::make_shared<GraphObj>());
// or
// objectList.push_front(std::make_unique<GraphObj>());
获取列表大小:
objectList.size();
遍历列表:
for (std::list<GraphObj*>::const_iterator it = objectList.begin();
it != objectList.end();
++it)
{
point start = (*it)->getStart();
// or whatever you need to do here
}
或者更好的范围:
for (const auto & graphObj : objectList)
{
point start = graphObj->getStart();
// or whatever you need to do here
}
因为你没有启动结构。
稍微更改构造函数
由此
Line(type t, std::string name) : GraphObj(t, name) {};
自
Line(type t, std::string name) : GraphObj(t, name) , start(),end() {};
这可能会有所帮助。
问题可能来自您的getStart和getEnd,因为它们返回一个点,这将创建您的起点或终点的副本(我认为(,即不使用行中的点而是副本。这通常没什么大不了的,但如果你想改变一个 x 或 y 值并让新的值坚持下去,你需要引用原始点 x 和 y 值。试试这个,改变
point getStart();
point getEnd();
到
point *getStart() { return &start; }
point *getEnd() { return &end; }
并在您的do_drawing(cairo_t *cr(更改
point start = g->getStart();
自
point *start = g->getStart();
start->x = value; // or
double value = start->x; // or however you want to use start