Russian Qt Forum

Программирование => С/C++ => Тема начата: labview от Август 13, 2010, 15:26



Название: Как правильно передать массив классов в конструктор?
Отправлено: labview от Август 13, 2010, 15:26
Всем привет!

Хочу передать один определённый массив классов в конструкторы двух других классов. Сделал так.

Класс первый:

Код:
#ifndef THREAD1_H
#define THREAD1_H

#include <QThread>

#include "Tasking.h"

class Thread1 : public QThread
{
    Q_OBJECT

public:
    Thread1(Tasking *allTasks[], int tasksCount);
private:
    virtual void run();
    Tasking *Tasks[];
signals:
    void showData(QString data);
};

#endif // THREAD1_H

Код:
#include "thread1.h"


Thread1::Thread1(Tasking *allTasks[], int tasksCount)
{
    for(int i = 0; i < tasksCount; i++)
    Tasks[i] = allTasks[i];
}

void Thread1::run()
{
    task myTask;
    myTask.tasknum = 1;
    myTask.data = "something";
    Tasks[0]->addTask(myTask);
    emit showData(myTask.data);
}

И аналогично Класс второй:
Код:
#ifndef THREAD2_H
#define THREAD2_H

#include <QThread>

#include "Tasking.h"

class Thread2 : public QThread
{
    Q_OBJECT

public:
    Thread2(Tasking *allTasks[], int tasksCount);
private:
    virtual void run();
    Tasking *Tasks[];
signals:
    void showData(QString data);
};

#endif // THREAD2_H

Код:
#include "thread2.h"

Thread2::Thread2(Tasking *allTasks[], int tasksCount)
{
    for(int i = 0; i < tasksCount; i++)
    Tasks[i] = allTasks[i];
}

void Thread2::run()
{
    task myTask;
    myTask = Tasks[0]->getTask();
    emit showData("Thread2");
}

В main.cpp делаю так:

Код:
#include <QtGui/QApplication>

#include "mainwidget.h"
#include "Tasking.h"
#include "thread1.h"
#include "thread2.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWidget w;
    w.show();

    Tasking *allTasks[1];

    Tasking *tasking1 = new Tasking;
    allTasks[0] = tasking1;
    Thread1 myThread1(allTasks, sizeof(allTasks));
    Thread2 myThread2(allTasks, sizeof(allTasks));

    QObject::connect(&myThread1, SIGNAL(showData(QString)), &w, SLOT(addText(QString)));
    QObject::connect(&myThread2, SIGNAL(showData(QString)), &w, SLOT(addText(QString)));

    myThread1.start();
    myThread2.start();
    myThread1.wait();
    myThread2.wait();

    return a.exec();
}

Если я проделываю это только с одним классом то всё ок, а если работают оба то получаю сегфолт.

Дело вот в этой строке конструктора второго класса:
Код:
    Tasks[i] = allTasks[i];

Если эту строку убрать, то прога работает.

Подскажите плиз в чём проблема.


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: m_ax от Август 13, 2010, 16:05
Может нужно вначале (перед использованием массива Tasks) выделить для него память?
Код
C++ (Qt)
   Tasks = new Tasking*[tasksCount];
 
а уже потом пытаться в него записывать.



Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: labview от Август 13, 2010, 16:14
Спасибо, теперь понятно, что нужно сначала выделить память, но компилятор ругается.
Код:
 incompatible types in assignment of 'Tasking**' to 'Tasking* [0]' 

И ещё вопрос, а почему оно работало с одним классом?


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: Igors от Август 13, 2010, 16:17
1) Если Вы хотите скопировать массив указателей, то память для приемника (куда копируется) должна быть выделена напр
Код
C++ (Qt)
Thread2::Thread2(Tasking *allTasks[], int tasksCount)
{
   delete [] Tasks;                               // не забыть обнулить Tasks в конструкторе
   Tasks = new Tasking * [tasksCount];
   for(int i = 0; i < tasksCount; i++)
    Tasks[i] = allTasks[i];
}


2)
Код:
Thread1 myThread1(allTasks, sizeof(allTasks));

sizeof возвращает размер структуры в байтах, а не число элементов в массиве. Есть классная макруха

Код
C++ (Qt)
#define ITEMCOUNT(a) (sizeof(a) / sizeof(a[0]))
 


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: Igors от Август 13, 2010, 16:27
Спасибо, теперь понятно, что нужно сначала выделить память, но компилятор ругается.
Код:
 incompatible types in assignment of 'Tasking**' to 'Tasking* [0]' 
Что такое Tasking* []' - во всяком случае мудрено понять  :)
Объявите проще: Tasking ** Tasks;


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: labview от Август 13, 2010, 16:33
Ок, так сделал. Переобьявил Tasks[] на **Tasks, с delete начала прога вылетать, убрал строки с delete, вроде заработало.

Макросами пока не пользовался, временно сделал вызов таким:
Код:
    Thread1 myThread1(allTasks, sizeof(allTasks)/sizeof(allTasks[0]));
    Thread2 myThread2(allTasks, sizeof(allTasks)/sizeof(allTasks[0]));

Вроде пока всё заработало.

Спасибо.

ЗЫ да C++ у меня хромает, сори, учусь.


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: Igors от Август 13, 2010, 16:47
Ок, так сделал. Переобьявил Tasks[] на **Tasks, с delete начала прога вылетать, убрал строки с delete, вроде заработало.
Просто убрать - ошибка, Вы должны удалять старый массив когда пришел новый, иначе получите утечку памяти. Проследите что Tasks инициализирован нулем в конструкторе.


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: labview от Август 13, 2010, 16:50
А как это сделать? И ещё мы ведь и так находимся в конструкторе, чем он может быть ещё инициализирован если обьект только только начинает своё существование?

Спасибо.


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: m_ax от Август 13, 2010, 16:58
Цитировать
Просто убрать - ошибка, Вы должны удалять старый массив когда пришел новый, иначе получите утечку памяти. Проследите что Tasks инициализирован нулем в конструкторе.

Да нафига в конструкторе то delete? Я понимаю, он (конструктор) без аргументов был, а запись массива производилась бы в какой-нить другой функции уже позже.. Тогда, да в конструкторе не грех и занулить Tasks = 0;
Но в данной ситуации delete в конструкторе - это ошибка.
Когда мы в конструкторе вызываем
Код
C++ (Qt)
delete [] Tasks;
 
что он будет пытаться удалить? Мусор))
 


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: Igors от Август 13, 2010, 17:09
Да нафига в конструкторе то delete?
Пардон, фигню спорол  :)  Совсем не увидел что это сам конструктор и есть - тогда конечно не надо


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: Nimbus от Август 16, 2010, 04:13
Код
C++ (Qt)
   for(int i = 0; i < tasksCount; i++)
    Tasks[i] = allTasks[i];
 

memcpy(Tasks, allTasks, sizeof(Tasking*) * tasksCount);
;)


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: SASA от Август 18, 2010, 14:23
Люди! Пользуйтесь QList, QSet, и т.д. Использвать сишные массивы надо только в КРАЙНЕМ случае.


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: Igors от Август 18, 2010, 14:34
Люди! Пользуйтесь QList, QSet, и т.д. Использвать сишные массивы надо только в КРАЙНЕМ случае.
Хмм... если человек еще не владеет С массивами и сразу начнет с контейнеров - получится совсем не гуд  :)


Название: Re: Как правильно передать массив классов в конструктор?
Отправлено: Sancho_s_rancho от Август 18, 2010, 15:33
Люди! Пользуйтесь QList, QSet, и т.д. Использвать сишные массивы надо только в КРАЙНЕМ случае.
Хмм... если человек еще не владеет С массивами и сразу начнет с контейнеров - получится совсем не гуд  :)
Согласен. Хотя недавно я тут читывал книгу для изучающих С++ от Страуструпа , так он сразу, с первых примеров, начинает показывать на векторах и с исключениями. Книга зовется "Principles and Practice Using C++" . Если учесть, что исключения в С++ - это еще тот геморрой (т.е. задумка хорошая, а вот реализация проблемная), а шаблонные классы внутрях часто содержат массивы, указатели и malloc/realloc/free, то такое засирание мозгов выглядит странным.
ПиСи "принципы и практика использования C++" - книга именно для начинающих, по ней Бьярн читает лекции молодым студентам.