LINUX.ORG.RU

Итераторы в qt.

 , ,


0

1

После руби это что-то трудноусваиваемое. Насколько я понимаю, когда я объявляю итератор, я в дальнейшем могу обращаться к нему как к текущему элементу. Но он делает мне от ворот поворот:

ошибка: no matching function for call to 'Line::Line(QListIterator<QGenericMatrix<3, 1, double> >&, Point&)'

Код такой:

QList<Line> Polygon::lines()
  {
    QList<Line> *lines = new QList<Line>;
    QListIterator<Point> point(*points);
    Line *current_line;
    while(point.hasNext()) {
        Point p = point.next();
        current_line = new Line(point, p);
        *lines << *current_line;
      }

    return *lines;
  }

// Конструктор Line
public:
  Line(Point a, Point b);

Я очень подозреваю, что опять где-то облажался с указателями, но ошибка говорит, что компилятор не будет конвертировать итератор в элемент списка. Я в недоумении.

★★

Последнее исправление: S-Mage (всего исправлений: 2)

Ответ на: комментарий от note173

с point.next() как раз все хорошо, он не может point обработать:

note:   no known conversion for argument 1 from 'QListIterator<QGenericMatrix<3, 1, double> >' to 'Point {aka QGenericMatrix<3, 1, double>}'
S-Mage ★★
() автор топика
Ответ на: комментарий от S-Mage

Ну надо же хоть иногда в документацию заглядывать. Это операторы в стиле java, там hasNext() ничего не делает, кроме проверки, не указывает ли итератор на конец коллекции, реальное значение следующего элемента получается через next(), одновременно итератор сдвигается к следующему элементу.

note173 ★★★★★
()
Ответ на: комментарий от nanoolinux

Line(i.next(), i.next()), тогда уж. Иначе упадет, если список пустой.

Да и просто упадет, потому что после первого next итератор указывает на нулевой элемент, после previous — на минус первый.

note173 ★★★★★
()
Последнее исправление: note173 (всего исправлений: 1)
Ответ на: комментарий от S-Mage

Вот такой несчастный костыль работает, но изврат же:

while(point.hasNext()) {
        Point p = point.next();
        Point p2 = point.previous();
        current_line = new Line(p2, p);
        *lines << *current_line;
        point.next();
      }
S-Mage ★★
() автор топика

C++ не делает магии с типами. point - это итератор, и С++ из него точку делать не будет.

Кроме того, QListIterator фактически указывает не на сам элемент, а на место перед ним, поэтому для него нет понятия текущий. Есть next() и previous(). И next() идет сразу за previuos(), а не через один.

Belkrr
()
Ответ на: комментарий от note173

блин, я не подумал, что previous итератор перемещает.

быстрофикс:

Point p1 = i.next();
Point p2;
while (i.hasNext()) {
  p2 = i.next();
  Line(p1, p2);
  p1 = p2;
}

nanoolinux ★★★★
()
Ответ на: комментарий от note173

Не успел исправить. Ещё однин вызов hasNext() в самом начале.

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

Это уже другая проблема, избежать можно проверкой на четность количества элементов.

note173 ★★★★★
()
QList<int> points;
QList<QPair<int,int> > lines;

points << 0 << 1 << 2 << 3 << 4 << 5;

if (!points.isEmpty())
{
    QListIterator<int> first(points);
    QListIterator<int> second(points);

    second.next();
    while(second.hasNext())
    {
        lines << QPair<int, int>(first.next(), second.next());
    }
}

QPair<int, int> line;
foreach(line, lines)
{
    qDebug() << line;
}

Прямолинейно и читабельно, на мой взгляд.

Belkrr
()

Кроме всего прочего, тут утечка на утечке. Не мешает почитать про выделение/освобождение памяти.

ratatosk
()
Ответ на: комментарий от nanoolinux

Так, теперь программа собирается, но валится, внезапно, вот здесь:

QList<Line> Polygon::lines()
  {
    QList<Line> *lines = new QList<Line>;
    QListIterator<Point> point(*points);
    // vvvvvvvvvvvvvvvvv
    Line *current_line;
    if(point.hasNext()) {
      Point p = point.next();
      Point p2;
      while(point.hasNext()) {
          p2 = point.next();
          *current_line = new Line(p, p2);
          *lines << *current_line;
          p = p2;
        }
      }

    return *lines;
  }

Отладчик говорит, что был вызван SIGSEGV, segmentation fault, то есть.

Еще Line теперь такой:

typedef QPair<Point, Point> Line;
S-Mage ★★
() автор топика
Ответ на: комментарий от S-Mage

Прочитайте хоть одну книжку по плюсам! Иначе потом начнете гнать, что С++ заморочен, туп и там вообще ад с указателями.

Не используйте new там, где он не нужен, конструируйте объекты напрямую в той точке, где они нужны.

Разберитесь с разыменованием указателей.

*current_line = new Line(p, p2); - вот, где ошибка. Уверен, что компилятор матом покрывает эту строку.

return *lines - тоже адский ад.

Belkrr
()
Ответ на: комментарий от Belkrr

Действительно, что-то я закопался в указателях. Еще дурацкий вопрос, раз уж я решил учиться сразу с примеров: как определить размер массива внутри функции, если массив - аргумент?

Polygon::Polygon(Point p[], bool cont)
  {
    int dim = sizeof(p) / sizeof(p[0]); // возвращает 0
    for(int i = 0; i < dim; i++) {
        points << p[i];
      }
    isContour = cont;
  }
S-Mage ★★
() автор топика
Ответ на: комментарий от S-Mage

Никак. Для аргументов функций этот прием не работает. Пользуйтесь контейнерами или передавайте размер в явном виде.

Belkrr
()

Вот это жесть Утечка памяти из-за lines и из-за каждого Line. Рекомендую использовать stl like итераторы. Я так понимаю Вы вообще не понимаете что такое указатели и что делает оператор new, когда он нужен и зачем. Ботайте основы.

Vernat ★★
()

Раз отметил как решенную, то вот что в итоге:

QList<Line> Polygon::lines()
  {
    QList<Line> lines;
    QListIterator<Point> point(points);
    if(point.hasNext()) {
      Point p = point.next();
      Point p2;
      while(point.hasNext()) {
          p2 = point.next();
          lines << Line(p, p2);
          p = p2;
        }
      if(isContour)
        lines << Line(points.first(), points.last());
      }

    return lines;
  }
S-Mage ★★
() автор топика
Ответ на: комментарий от annulen

Я уже тоже решил так и делать, stl-like более интуитивны, чтоли.

S-Mage ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.