Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] QList, полное непонимание =(


Автор: kemiisto 27.8.2009, 13:25
Что-то я совсем ничего не понимаю. Есть у меня класс Atom
Код

namespace Chemistry
{
  class Atom
  {
  public:
    ...
    void bondWith(int index);
    
  private:
    ...
    QList<int> bondedIndexes_;
  };
} // namespace Chemistry


Привёл только ту часть, что по моему мнению имеет отношение к делу. 

bondedIndexes_ хранит индексы атомов, с которыми данный атом связан.

Метод bondWith(int index) вносит index в этот список:
Код

void Chemistry::Atom::bondWith(int index)
{
  bondedIndexes_.append(index);
}


Далее есть класс Molecule:
Код

namespace Chemistry
{
  class Molecule
  {
  public:
    ...
    void rebond();

  private:
    ...
    QList<Chemistry::Atom>* atoms_;
  };
} // namespace Chemistry


В методе rebond следующий код:
Код

void Chemistry::Molecule::rebond()
{
  for (int i = 0; i < atomsCount() - 1; ++i)
  {
    for (int j = i + 1; j < atomsCount(); ++j)
    {
      if (interatomicDistance(i, j) <
          atom(i).covalentRadius() + atom(j).covalentRadius() + tolerance)
      {
        atoms_->value(i).bondWith(j);
        atoms_->value(j).bondWith(i);
      }
    }
  }
}


Тут не суть важно условие, главное, что bondWith() вызывается.

Беда в том, что при каждом вызове bondWith() список bondedIndexes_ почему то оказывается пустым. В него добавляется index. Но при следующем вызове список снова пуст. И в конце вызова rebond() у всех атомов список bondedIndexes_ оказывается пустым. smile 

HELP!!!

Автор: just_geek 27.8.2009, 13:45
Так это

Код

QList<Chemistry::Atom>* atoms_;

Мне кажется или нужно сделать так 

Код

QList<Chemistry::Atom*> atoms_;


update
а лучше, заменить 
Код

atoms_->value(i).bondWith(j);
// на
atoms_->at(i).bondWith(j);

так как value возвращает новый объект.

Автор: kemiisto 27.8.2009, 14:50
Цитата(just_geek @  27.8.2009,  14:45 Найти цитируемый пост)
Мне кажется или нужно сделать так

Изначально было так:
Код

namespace Chemistry
{
  class Molecule
  {
  public:
    ...
    void rebond();
  private:
    ...
    QList<Chemistry::Atom> atoms_;
  };
} // namespace Chemistry


Код

void Chemistry::Molecule::rebond()
{
  for (int i = 0; i < atomsCount() - 1; ++i)
  {
    for (int j = i + 1; j < atomsCount(); ++j)
    {
      if (interatomicDistance(i, j) <
          atom(i).covalentRadius() + atom(j).covalentRadius() + tolerance)
      {
        atoms_.value(i).bondWith(j);
        atoms_.value(j).bondWith(i);
      }
    }
  }
}


Работает точно также. В смысле, не работает. smile 


Цитата(just_geek @  27.8.2009,  14:45 Найти цитируемый пост)

Код

QList<Chemistry::Atom*> atoms_;


Можно, конечно, попробовать. Не хочеться иметь список указателей. А это точно что-то изменит?

Цитата(just_geek @  27.8.2009,  14:45 Найти цитируемый пост)

так как value возвращает новый объект.

Разве? smile

Добавлено через 2 минуты и 59 секунд
Цитата(kemiisto @  27.8.2009,  15:50 Найти цитируемый пост)
Разве?

Тьфу! И верно! Надо доступ через [] использовать.
Код

atoms_[i].bondWith(j);

Автор: kemiisto 27.8.2009, 17:24
Продолжаем КВН. smile 

Теперь такая беда. Есть такой вот класс:
Код

namespace Render
{
  class Viewer : public QGLViewer
  {
    Q_OBJECT
    ...
  protected:
    virtual void mousePressEvent(QMouseEvent* e);
    ...

  private:
    ...
    Chemistry::Molecule molecule_;
};


После того, как отработает конструктор по умолчанию, создаётся объект molecule_. У которого создаётся пустой список atoms_. Всё цивильно. Но стоит потом вызваться методу, скажем, mousePressEvent(), в котором есть такое место:
Код

Chemistry::Atom chemistryAtom; // создали атом
chemistryAtom.setProtons(atomicNumber_); // установили свойства
molecule_->addAtom(chemistryAtom); // пытаемся добавить

приложение падает. smile 

И писало что-то типа QList: Out of memory. А в режиме отладки напротив этого самого QList значилось <internal error>. Немного погуглив, я наткнулся на http://www.qtcentre.org/forum/archive/index.php/t-7257.html. 

Переделал чуток, сделав Chemistry::Molecule* molecule_ ну и там в конструкторе явно вызываю:
Код

molecule_ = new Chemistry::Molecule();


Теперь оно падает просто без сообщений. А в режиме отладки напротив этого самого QList значицо <out of scope>.

HELP!!!

Автор: just_geek 27.8.2009, 17:33
А на каких строках падало в обоих случаях? Такое ощущение, что либо память портишь сам. Либо вызываешь функцию не созданного класса.

Автор: kemiisto 27.8.2009, 17:37
Цитата(just_geek @  27.8.2009,  18:33 Найти цитируемый пост)
А на каких строках падало в обоих случаях? Такое ощущение, что либо память портишь сам. Либо вызываешь функцию не созданного класса. 

Падает он на:
Код

molecule_->addAtom(chemistryAtom);

а там собственно:
Код

void Chemistry::Molecule::addAtom(const Chemistry::Atom& atom)
{
  atoms_.append(atom);
}

Автор: just_geek 27.8.2009, 17:46
Код

molecule_->addAtom(chemistryAtom);

ну и чему в этом месте равно значение указателя?

molecue_ то к этому моменту создано?

Автор: kemiisto 27.8.2009, 17:53
Цитата(just_geek @  27.8.2009,  18:46 Найти цитируемый пост)
ну и чему в этом месте равно значение указателя?

http://ipicture.ru/

Автор: just_geek 27.8.2009, 18:06
гхм

а если дальше внутрь функции 
Код

molecule_->addAtom(chemistryAtom); // пытаемся добавить


пройти ? может где то внутри падает?

Автор: kemiisto 27.8.2009, 18:13
just_geek, да там код то одна строчка:
Код

void Chemistry::Molecule::addAtom(const Chemistry::Atom& atom)
{
  atoms_.append(atom);
}

Падает при добавлении элемента. Если в debug'е - то останавливается на:
Код

    inline bool operator!=(int value) const
    {
        return _q_value != value;
    }

из qbasicatomic.h.

Автор: kemiisto 28.8.2009, 11:40
Пытался менять QList на QVector, std::list, std::vector. Никакой разницы. smile 

Автор: andrew_121 28.8.2009, 13:35
пересобири Qt(единственное что на ум пришло).

Автор: kemiisto 28.8.2009, 13:41
andrew_121, я уж на 3 разных сборках тестил на 3-х разных ОС'ях. Не работает. smile 

Автор: fearuth 28.8.2009, 14:21
Попробуй atoms_.append(atom) заменить на:

Код

atoms_<<atom;

Автор: kemiisto 28.8.2009, 14:22
fearuth, пробовал уже. Это одно и тоже. И результат такой же.

Автор: fearuth 28.8.2009, 14:27
Может глупость, но зачем знак "_" в конце имени? Попробуй без него. +)

Автор: kemiisto 28.8.2009, 14:38
Цитата(fearuth @  28.8.2009,  15:27 Найти цитируемый пост)
Может глупость, но зачем знак "_" в конце имени?

Это я так private-члены обозначаю. Довольно распространённый способ. Это не повлияет ни на что. smile 

Автор: kemiisto 30.8.2009, 18:09
Up!  Помогите! smile 

Автор: andrew_121 30.8.2009, 19:04
Выложи весь проект куда-то. Если не секрет конечно smile 

Автор: kemiisto 30.8.2009, 19:16
andrew_121, не секрет. Если что-то из этого получиться оно будет Open Source. 

Если не жалко времени, конечно. 

Нужно собрать вот эту http://www.libqglviewer.com/. Ты ведь линуксоид. Если из сорсов соберёшь, пути в *.pro должны быть правильные.

От хлама вроде почистил...

Автор: andrew_121 30.8.2009, 19:21
Цитата(kemiisto @  30.8.2009,  19:16 Найти цитируемый пост)
Ты ведь линуксоид.

Да. Но собиру под виндавз. Просто сейчас не могу перегрузиться.
Оно ведь кросс?

Автор: kemiisto 30.8.2009, 19:32
Цитата(andrew_121 @  30.8.2009,  20:21 Найти цитируемый пост)
Оно ведь кросс?

Ага. Только если для debug собирать - убери строчку
Код
CONFIG -= debug debug_and_release

из libQGLViewer-2.3.3\QGLViewer\. Собранную либу кинь QDalton\Libraries\, dll - в Binaries\Windows\.

Хотя ты лучше меня в этом смыслишь...

Автор: andrew_121 30.8.2009, 20:35
Цитата(kemiisto @  30.8.2009,  19:32 Найти цитируемый пост)
из libQGLViewer-2.3.3\QGLViewer\. Собранную либу кинь QDalton\Libraries\, dll - в Binaries\Windows\.

С этим я согласен. Но вот хидеры libQGLViewer и Eigen включать в поставку проекта не правильно. Это сторонние проекты.

Автор: kemiisto 30.8.2009, 21:25
Цитата(andrew_121 @  30.8.2009,  21:35 Найти цитируемый пост)
Но вот хидеры libQGLViewer и Eigen включать в поставку проекта не правильно. Это сторонние проекты.

Согласен, но речи о поставке пока не идёт. smile 

Автор: kemiisto 30.8.2009, 22:50
andrew_121, я дико извиняюсь. Не ту версию приаттачил. Перезакачай, если не напряжно. Там проблема из начала топика решена. Но атомы в молекулу не добавить...

Автор: andrew_121 30.8.2009, 23:47
kemiisto, Обновился.

Автор: andrew_121 31.8.2009, 04:16
 smile 
http://ipicture.ru/

Собрал с костылями. Приведу в порядок, выложу.

Автор: andrew_121 31.8.2009, 06:22
Как и обещал, выкладываю. Собрал - Win32-debug|release, Linux-release.
http://rghost.ru/430404

Вкратце. Проблема была не в коде, а в сборке. Нельзя для debug сборки использовать release библиотеки, и на оборот.

п.с.
Кто программу писал?

Автор: kemiisto 31.8.2009, 10:24
andrew_121,  smile Спасибо большое!


Цитата(andrew_121 @  31.8.2009,  07:22 Найти цитируемый пост)
Вкратце. Проблема была не в коде, а в сборке. Нельзя для debug сборки использовать release библиотеки, и на оборот.

Я так понимаю, проблема была в *.pro файле?

Цитата(andrew_121 @  31.8.2009,  07:22 Найти цитируемый пост)
Кто программу писал?

Это моя поделка. smile 

Автор: andrew_121 31.8.2009, 10:34
Цитата(kemiisto @  31.8.2009,  10:24 Найти цитируемый пост)
Я так понимаю, проблема была в *.pro файле?

Именно.

Цитата(kemiisto @  31.8.2009,  10:24 Найти цитируемый пост)
Это моя поделка. smile  

Удивительно... Тогда не понятно твое недовольство языком С++. Довольно высокое качество кода. Лучше большинства проектов выставленных на http://qt-apps.org/
Можешь смело размещать проект.

Автор: kemiisto 4.9.2009, 21:35
andrew_121, опять та же ситуация. Исходники несколько изменились. Теперь у нас в private секции Chemistry::Molecule сразу 3 QList'а (к тому же один со сложной структурой):
Код

  private:
    typedef QList<Chemistry::Bond*> IncidenceList;
    typedef QList<IncidenceList> IncidenceMatrix;

    IncidenceMatrix incidenceMatrix_;
    QList<Chemistry::Bond*> chemistryBonds_;
    QList<Chemistry::Atom*> chemistryAtoms_;


Ну собственно, таже проблема. Отрабатывает конструктор, все 3 списка инициализируются. 

user posted image

При попытке добавить атом в Render::Viewer::mousePressEvent в самом начале ставим точку останова:

user posted image

Вот. Куда то пропал incidenceMatrix_. Куда?

А самое интересное. Если в объявлении поменять местами скажем так:
Код

  private:
    typedef QList<Chemistry::Bond*> IncidenceList;
    typedef QList<IncidenceList> IncidenceMatrix;

    QList<Chemistry::Bond*> chemistryBonds_;
    QList<Chemistry::Atom*> chemistryAtoms_;
    IncidenceMatrix incidenceMatrix_;

то на точке останова не будет уже chemistryBonds_

user posted image

То есть получается: кто первым объявлен (первым инициализируется в конструкторе?), тот куда-то пропадает. smile Бред, конечно. smile Может опять чего в pro-файле начудил. smile 

Исходники приложил.

Автор: kemiisto 4.9.2009, 22:35
Немного побегал дебагом. Список портится внутри void Render::Viewer::updateMolecule().

До вызова updateGL() всё отлично, после <internal error>. А это метод (точнее слот) QGLViewer'а. И это уже как-то нехорошо...

Автор: andrew_121 4.9.2009, 22:54
Цитата(kemiisto @  4.9.2009,  21:35 Найти цитируемый пост)
То есть получается: кто первым объявлен (первым инициализируется в конструкторе?

Да. В GCC это так.

Цитата(kemiisto @  4.9.2009,  21:35 Найти цитируемый пост)
Бред, конечно.

Да нет же. Это в стандарте описано.

Цитата(kemiisto @  4.9.2009,  21:35 Найти цитируемый пост)
Может опять чего в pro-файле начудил.

Не ты. Это креатор его по своему записал(если ты менял проект, не исходники).

щас гляну...

Автор: kemiisto 5.9.2009, 11:06
Цитата(andrew_121 @  4.9.2009,  23:54 Найти цитируемый пост)
Да нет же. Это в стандарте описано.

Я не про порядок вызова конструкторов, а про ситуацию в целом. Я чего то явно не понимаю. А, вообще, язык - полное *****. Как на нём вообще возможно писать? Никогда не знаешь, кто виноват: ты, разработчики компилятора, сторонней библиотеки или стандарта, оставившие слишком много мест с undefined dehaviour, ОС, господь бог, ... smile 

Автор: kemiisto 5.9.2009, 12:17
Жесть. Ночь не спал, а толку 0.

andrew_121, зато я нашёл прикол в своих исходниках.
Вот функция:
Код

uint8_t File::Dal::moduleIndex(const QString& moduleName)
{
  for (uint8_t i = 0; i < modules_.size(); ++i)
  {
    if (modules_[i].name() == moduleName + "\n")
      return i;
  }
  return -1;
}

Это компилируется. Ерунда, что тип возвращаемого значения беззнаковый, а в одной из веток if я возвращаю -1! smile Нормуль! Ругается только по месту вызова этой функции:
Код

bool File::Dal::hasParametre(const QString& moduleName,
                                  const QString& submoduleName,
                                  const QString& parametreName)
{
  uint8_t m = moduleIndex(moduleName);
  if (m != -1)

И то warning.

Вот это, видимо, и называется строгая типизация. smile 

Автор: andrew_121 5.9.2009, 14:39
kemiisto, Снова в ту же степь. Знаешь что плохому танцору мешает? Вот вот, я***.
По делу: Нет пока возможности собрать твою программу. Попробуй просто прежний .pro файл подкинь. По идее должно заработать.

Автор: kemiisto 5.9.2009, 14:41
Цитата(andrew_121 @  5.9.2009,  15:39 Найти цитируемый пост)
kemiisto, Снова в ту же степь. Знаешь что плохому танцору мешает? Вот вот, я***.

 smile Дык я же и не спорю. Я плохой танцор. Но я же не один такой. Нас много!

Цитата(andrew_121 @  5.9.2009,  15:39 Найти цитируемый пост)
По делу: Нет пока возможности собрать твою программу. Попробуй просто прежний .pro файл подкинь. По идее должно заработать. 

Сейчас попробую.

Автор: kemiisto 5.9.2009, 15:47
Цитата(kemiisto @  5.9.2009,  15:41 Найти цитируемый пост)
Сейчас попробую. 

Нет, видимо, не в этом дело.

Автор: andrew_121 5.9.2009, 16:26
Цитата(kemiisto @  5.9.2009,  15:47 Найти цитируемый пост)
Нет, видимо, не в этом дело. 

А под Мас-ом работает?

Автор: kemiisto 5.9.2009, 16:36
Цитата(andrew_121 @  5.9.2009,  17:26 Найти цитируемый пост)
А под Мас-ом работает? 

Нет. Нигде не работает.

Автор: andrew_121 5.9.2009, 16:39
Цитата(kemiisto @  5.9.2009,  16:36 Найти цитируемый пост)
Нет. Нигде не работает. 

Значит ошибка в коде.

Автор: Lazin 5.9.2009, 16:40
kemiisto, у тебя этот объект копируется где нибудь? (в смысле не указатель на него, а именно сам объект, deep copy)

Автор: kemiisto 5.9.2009, 16:55
Цитата(Lazin @  5.9.2009,  17:40 Найти цитируемый пост)
kemiisto, у тебя этот объект копируется где нибудь? (в смысле не указатель на него, а именно сам объект, deep copy) 

Не очень понял о каком конкретно объекте идёт речь. Если о chemistryMolecule_, то да. Читаем файл, разбираем, создаём молекулу, передаём вьюверу для отрисовки через void Render::Viewer::setMolecule(const Chemistry::Molecule& chemistryMolecule)
 
Цитата(andrew_121 @  5.9.2009,  17:39 Найти цитируемый пост)
Значит ошибка в коде. 

Вот я её и пытаюсь локлизовать.

Автор: Lazin 5.9.2009, 19:42
Цитата(kemiisto @  5.9.2009,  16:55 Найти цитируемый пост)
Не очень понял о каком конкретно объекте идёт речь. Если о chemistryMolecule_, то да. Читаем файл, разбираем, создаём молекулу, передаём вьюверу для отрисовки через void Render::Viewer::setMolecule(const Chemistry::Molecule& chemistryMolecule)



Цитата(kemiisto @  27.8.2009,  13:25 Найти цитируемый пост)
namespace Chemistry
{
  class Molecule
  {
  public:
    ...
    void rebond();
  private:
    ...
    QList<Chemistry::Atom>* atoms_;
  };
} // namespace Chemistry


я имел ввиду, что объект класса Molecule, может где-нибудь копироваться полностью, ты ведь не определил свой конструктор копирования для него, значит компилятор сделал это за тебя, возможно ты где-то передаешь этот объект по значению, и этот конструктор вызывается и что-то идет не так
попробуй определить свой копирующий конструктор и оператор присваивания так -

Код

class Molecule
{
...
private:
   Molecule(Molecule const&);
   Molecule& operator = (Molecule const&);

если код по прежнему будет компилироваться, то проблема в чем-то другом smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)