Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Чтение/Запись вектора указателей из/в файл
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
Not_Once
Доброго времени суток! Не судите строго - опыта мало. Вообщем, нужна помощь, уже в конец запутался. Весь проект, естественно тащить не буду, попытаюсь на примере.
Допустим, имею:
1) Класс Cube c разнородной информацией и де-/сериализатором для потока.
Раскрывающийся текст
class Cube
{
public:

    bool a;
    int  b;
    char c;
    
    friend QDataStream &operator<< (QDataStream &write, const Cube &cb);
    friend QDataStream &operator>> (QDataStream &read, Cube &cb);
};

QDataStream &operator<< (QDataStream &write, const Cube &cb)  //Сериализация
{
    write << cb.a;
    write << cb.b;
    write << cb.c;
    return write;
}

QDataStream &operator>> (QDataStream &read, Cube &cb)  //Десериализация
{
    read >> cb.a;
    read >> cb.b;
    read >> cb.c;
    return read;
}


2) Класс Data с объявленным вектором указателей на объекты Cube и методами записи/чтения в данных из/в файл
Раскрывающийся текст

class Data
{
public:

    QVector<Cube*>  *Data_Cubes; //Данные по кубам

    void save(QVector<Cube*>  *Cubes);//Запись в файл
    void load(QVector<Cube*>  *Cubes);//Чтение из файла
};

void Data::save(QVector<Abonent *> &Cubes)
{
    QFile File("Cube.dat");
    if(File.open(QIODevice::WriteOnly))
    {
        QDataStream write(&File);
        write << Cubes;  //В стандартной библиотеке сериализатор для QVector описан
    }
    //Проверки различные и выводы сообщений, касаемые файла и потока опустим
}

void Data::load(QVector<Abonent *> &Cubes)
{
    QFile File("Cube.dat");
    if(File.open(QIODevice::ReadOnly))
    {
        QDataStream read(&File);
        read >> Cubes;  //В стандартной библиотеке десериализатор для QVector описан
    }
    //Проверки различные и выводы сообщений, касаемые файла и потока опустим
}


3)В QDaraStream предусмотрены де-/сериализатор для QVector:
Раскрывающийся текст

template<typename T>
QDataStream& operator<<(QDataStream& s, const QVector<T>& v)
{
    s << quint32(v.size());
    for (typename QVector<T>::const_iterator it = v.begin(); it != v.end(); ++it)
        s << *it;
    return s;
}

template<typename T>
QDataStream& operator>>(QDataStream& s, QVector<T>& v)
{
    v.clear();
    quint32 c;
    s >> c;
    v.resize(c);
    for(quint32 i = 0; i < c; ++i) {
        T t;
        s >> t;
        v[i] = t;
    }
    return s;
}


4)Основное окно, с общей информацией, откуда вызываю запись и чтение данных
Раскрывающийся текст

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private:
    Ui::MainWindow *ui;
    
    Data    *Data_common;//Общие данные
};


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    Data_common = new Data;
    Data_common->load(*Data_common->Data_Cubes);//Чтение
}

MainWindow::~MainWindow()
{
    delete ui;
    Data_common->save(*Data_common->Data_Cubes);//Запись
    /// Есть ли необходимость в удалении указателя? (обнуление для избежания проблем)
    delete Data_common;
    Data_common=0;
}



При текущем варианте, данные пишутся и читаются в десериализаторе Cube, но сам вектор забивается последним объектом и программа вылетает. Я уже вконец запутался с указателями и объектами.
Вопрос: подскажите, что делаю не так?
Trisch
Я вот тоже в указателях иногда путаюсь. Но вот думаю что проблема может быть тут:
QVector<Cube*>  *Data_Cubes;


сделайте так:
QVector<Cube>  *Data_Cubes; // указатель на вектор который хранит хначения Cube
//или так
QVector<Cube*>  Data_Cubes; // вектор который хранит указатели на значения Cube
//или так
QVector<Cube>  Data_Cubes; // вектор который хранит значения Cube


правильный вариант зависит от того что вам надо.
Not_Once
Цитата(Trisch @ 13.3.2014, 19:58) *
сделайте так:
QVector<Cube>  *Data_Cubes; // указатель на вектор который хранит хначения Cube
//или так
QVector<Cube*>  Data_Cubes; // вектор который хранит указатели на значения Cube
//или так
QVector<Cube>  Data_Cubes; // вектор который хранит значения Cube


правильный вариант зависит от того что вам надо.


Спасибо за ответ :rolleyes:
Мне нужен именно Вектор Указателей, который будет хранить объекты Cube. А вот объектом:
QVector<Cube*>  Data_Cubes; // вектор который хранит указатели на значения Cube

или указателем:
QVector<Cube*>  *Data_Cubes; // указатель на вектор который хранит указатели на значения Cube

реализовывать - я не знаю.
Попробовал вариант с объектом (QVector<Cube*> Data_Cubes) - ничего не изменилось :unsure:
К сожалению ошибку допустил в описании проблемы, а именно класса Cube(для де-/сериализации подкладываю не объект Cube а указатель на него, того требует описанная де-/сериализация в QDatastream):

Раскрывающийся текст
class Cube
{
public:

    bool a;
    int  b;
    char c;
    
    friend QDataStream &operator<< (QDataStream &write, const Cube *cb);
    friend QDataStream &operator>> (QDataStream &read, Cube *cb);
};

QDataStream &operator<< (QDataStream &write, const Cube *cb)  //Сериализация
{
    write << cb->a;
    write << cb->b;
    write << cb->c;
    return write;
}

QDataStream &operator>> (QDataStream &read, Cube *cb)  //Десериализация
{
    read >> cb->a;
    read >> cb->b;
    read >> cb->c;
    return read;
}
Iron Bug
сериализация не работает с указателями. хранить указатели в файле - это безумие. сериализация работает только с объектами. поэтому сериализовать/десериализовать нужно сами объекты, а массив указателей создавать параллельно этому процессу, добавляя указатели на десериализованные объекты по мере их создания.
Not_Once
Цитата(Iron Bug @ 14.3.2014, 9:02) *
сериализация не работает с указателями. хранить указатели в файле - это безумие. сериализация работает только с объектами. поэтому сериализовать/десериализовать нужно сами объекты, а массив указателей создавать параллельно этому процессу, добавляя указатели на десериализованные объекты по мере их создания.


Огромное спасибо! :clapping:
Переделаю - отпишусь.
liamm
У меня тоже была необходимость сериализовать вектор указателей (назовем его QVector<SomeClass*> myVector), решение выглядит так:

class SomeClass{
  private:
    QString mSomeField;
  public:
    SomeClass();
  
    friend QDataStream &operator>>(QDataStream &in, SomeClass *inp);  
    friend QDataStream &operator<<(QDataStream &out, const SomeClass *inp);

};


операторы для сериализации/десериализации объекта по указателю:

QDataStream &operator<<(QDataStream &out, const SomeClass *inp){ //сериализация данных в поток
    out<<inp->mSomeField;
    return out;
}
QDataStream &operator>>(QDataStream &in, SimpleParam *inp){ //десериализация из потока
    in>>inp->mSomeField;
    return in;
}


сериализация вектора (сначала записываем в поток число элементов, потом данные для самих элементов)
 QVector<SomeClass*> myVector;
  ....
QDataStream inFile(&writeFile);

    inFile<<myVector.size();
    for(int i=0; i<myVector.size(); i++){
         inFile<<myVector[i];
    }


десериализация вектора (сначала вытаскиваем число элементов, потом данные для самих элементов, и заполняем на их основе вектор) :
QVector<SomeClass*> myVector;

QDataStream outFile(&readFile);
    int size=0;
    outFile>>size;
    for(int i=0; i<size; i++){
        SomeClass *item=new SomeClass();
        outFile>>item;
        myVector.append(item);
    }
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.