Adam Radomski Adam Radomski - 2 months ago 34
C++ Question

Two dimensional array Qt, initialization and usage

Maybe I'm just tired and I don't think clear enough or maybe I am such a noob in Qt programming but I got problem with initializing and usage of two dimensional array.

I created OutputData class which looks like this:

#ifndef OUTPUTDATA_H
#define OUTPUTDATA_H

#include <QObject>
#include "algorithms/data/tabledata.h"
#include <QVector>
#include <QDebug>
class OutputData : public QObject
{
Q_OBJECT
Q_ENUMS(direction)
public:
explicit OutputData(const int xSize, const int ySize, QObject *parent = 0);
enum direction {left, front, right, back };
double rightDistance;
double leftDistance;
double frontDistance;
int xShift;
int yShift;
direction currentDir;
int turnCount;
int currentDirection;
TableData** table;
QString toString();
void saveFieldInfo();
signals:

public slots:

private:

};

#endif // OUTPUTDATA_H


and of course cpp file:

#include "outputdata.h"

OutputData::OutputData(const int xSize,const int ySize, QObject *parent) :
QObject(parent)
{
// Nie chce mi sie bawić z ujemnymi wartościami to zaczynam od 2996 skrętu w prawo.
//Jak kiedyś robot skręci 2996 razy pod rząd w lewo to się będę tym przejmował
currentDir=front;
currentDirection = 2996;

rightDistance =0;
leftDistance = 0;
frontDistance = 0;
xShift =0;
yShift =0;
turnCount =0;

// vector = new QVector<QVector<TableData*> >(10, QVector<TableData*>(10));
table =new TableData*[ySize];
for(int i = 0; i < ySize; i++){
table[i] = new TableData[xSize];
}
for(int i = 0; i < ySize; i++){
for(int j = 0; j < xSize; j++){
table[i][j] = TableData();
}
}
}




void OutputData::saveFieldInfo(){
qDebug() << "save field info " << "rightDistance " << rightDistance << " leftDistance" << leftDistance << " frontDistance " << frontDistance
<< " currentDirection " << currentDirection;
table[yShift][xShift].fillWithData(rightDistance,leftDistance,frontDistance,currentDirection);
}


QString OutputData::toString(){
QString* string = new QString("{\"rightDistance\": \"\"");
string ->append(",\"leftDistance\": \"\"");
string->append(",\"frontDistance\": \"\"");
string->append(",\"xShift\": \"\"");
string->append(",\"yShift\": \"\"");
string->append(",\"currentDir\": \"\"");
string->append(",\"turnCount\": \"\"");
string->append(",\"currentDirection\": \"\"}");
return *string;
}


TableData
class is simple holder for primitive values such as direction, distance etc. Nothing special.

Here's my problem: I want to have two dimensional array of
TableData
where I can keep data which can be provided in random order but always with proper coordinates. (hope that this is understandable)

When I try to compile this code I receive error that I don't understand.


/home/adam/Qt/5.2.1/gcc_64/include/QtCore/qglobal.h:979: błąd:
'QObject& QObject::operator=(const QObject&)' is private
Class &operator=(const Class &) Q_DECL_EQ_DELETE;
^


(this error points at line class TableData : public QObject in TableData file)

and second:


/home/adam/Dropbox/workspace/git/qt/Raspberry/Raspberry/algorithms/data/tabledata.h:7:
błąd: within this context class TableData : public QObject
^


(this error points at 979 line of qglobal.h)

So I think (better: I'm pretty sure) I did something wrong. But I really don't know what!

Is there a better way to work on two dimensional array? How to initialize and use it? I know there plenty of examples on the web but most of them use double or int and I want to use my class
TableData
. They also make this arrays in specific function and I want that this array was available in whole class.

======= EDIT
As suggested I decide to use QVector but when I try to initialize it I got this error:


/home/adam/Dropbox/workspace2013.02/magisterka/git/qt/Raspberry/Raspberry/algorithms/data/outputdata.cpp:18:
błąd: no match for 'operator=' (operand types are
'QVector >' and 'QVector >*')
table = new QVector >(10, QVector(10));
^


in outputdata.h

QVector<QVector<TableData*> > table;


in outputdata.cpp

table = new QVector<QVector<TableData*> >(10, QVector<TableData*>(10));


This line generates error. How to fix it?

Later if I want to use this table did field of this table will be initialized or not?

Is this legal:

table[x][y].method();


or should I do it like this:

if(table[x][y] ==NULL){
table[x][y] = new TableData();
}
table[x][y].method();


Sorry for java style:(

Answer

Your TableData class is a subclass of QObject and so cannot be copied or copy assigned. That's why you are getting the compilation errors.

Your array should work with pointers to TableData instances i.e. create your TableData instances using new. Your table declaration should be

TableData*** table;

Rather than use a built-in array though you might be better off using containers. I notice that you have a line commented out that is using a QVector of QVectors of TableData* so I'm not sure whether you are trying to port the container approach to built-in arrays or not. Probably best to stick with the containers unless you have a good reason not to.


To answer your edit, I think you are getting confused between Java and C++. In C++ you only need new to do dynamic memory allocation. It returns a pointer. Your table variable is already declared as a QVector rather than a pointer to one so the storage for it will be set up when you instantiate the class. All you need to do is something like

OutputData::OutputData(const int xSize,const  int ySize, QObject *parent) :
    QObject(parent),
    table(ySize) // resize to ySize (empty) rows
{
    for(int i = 0; i < ySize; i++){
        QVector<TableData*>& row = table[i];
        row.resize(xSize); // Each TableData pointer will be initialised to NULL
        for(int j = 0; j < xSize; j++){
            row[j] = new TableData();
        }
    }
    // ...

Only TableData itself needs to be allocated with new. Since the TableData elements are pointers you will need to access them like

table[x][y]->method();