PDA

View Full Version : Linker does not accept overloaded "operator>>"



ZikO
30th August 2012, 19:32
Hi,
I've got a linker error; that is, it does not accept this expression:

stream << my_object.field
where the field is of qint16 type.

Generally, the program is supposed to test whether there is a file called "database" in the same folder as the application. If it does not exists, it is created. If it does exist, then the application connects to a database and fetch the date and time of fields modification. If the datetime of a file is earlier then the database, then the file on HDD is overwritten with new data. I have two problems here. The linker does not accept overloaded operators << and >>:

D:\Documents\Programming C++\Qt\wydarzenia\stworz_plik\stworz_plik\rekord.c pp:20: error: no match for 'operator>>' in 'stream >> r.Rekord::przypomnienie'
When I tried to overload operators << and >> for qint16, although it looked strange I'd have to do so, I've got segmentation error. I suspect it is due to line 33 in file "definicje_globalne.h" where data are sent to a stream associated with a file on HDD. I cannot find the cause of error. I hope providing all codes will make understand what I am trying to do and help me with the error. I will be grateful for any help and comments.

Thanks



plik.pro


SOURCES += \
main.cpp \
rekord.cpp

HEADERS += \
definicje_globalne.h \
rekord.h

QT += sql


main.cpp:


#include <QtGui>
#include <QtSql>
#include "rekord.h"
#include "definicje_globalne.h"

int main(int argc, char* argv[]) {
QApplication app(argc,argv);

QString fileName = "database";
QFile dbFile(fileName);
if(dbFile.exists()) {
qDebug() << "Plik database istnieje na dysku"; // "The file database exists"
bool isUpdated;
testUpdate(fileName,isUpdated);
if(!isUpdated) {
qDebug() << "Plik database jest nieuaktualny"; // "The file database is not up to date"
if(createFile(dbFile)) {
qDebug() << "Plik database zostal stworzony";
} else {
qDebug() << "Wystapil blad w tworzeniu poliku database";
}
} else {
qDebug() << "Plik database jest aktualny"; // "The file database is up to date"
} // if(!isUpdated)
} else {
qDebug() << "Plik database nie istnieje na dysku. Tworzenie pliku database."; // "The file database is not found. The file is being created ..."
createFile(dbFile);
}
return app.exec();
}


rekord.h



#ifndef REKORD_H
#define REKORD_H
#include <QString>
#include <QDate>
#include <QtGlobal>

struct Rekord {
QString imie; // name
QString nazwisko; // surname
QString nazwa_wyd; // event name
QDateTime data_wyd; // event date
qint16 przypomnienie; // remainder

Rekord(
const QString& im = "",
const QString& na = "",
const QString& nw = "",
const QDateTime& dw = QDateTime::currentDateTime(),
const qint16& p = 0
);
};

QDataStream& operator<<(QDataStream& stream, const Rekord& r);
QDataStream& operator>>(QDataStream& stream, Rekord& r);
//QDataStream& operator<<(QDataStream& stream, const qint16& qi);
//QDataStream& operator>>(QDataStream& stream, const qint16& qi);

#endif // REKORD_H


rekord.cpp



#include "rekord.h"

Rekord::Rekord(const QString& im, const QString& na, const QString& nw, const QDateTime &dw, const qint16& p)
: imie(im),nazwisko(na),nazwa_wyd(nw),data_wyd(dw),p rzypomnienie(p) {}

QDataStream& operator<<(QDataStream& stream, const Rekord& r) {
stream << r.imie;
stream << r.nazwisko;
stream << r.nazwa_wyd;
stream << r.data_wyd;
stream << r.przypomnienie;
return stream;
}

QDataStream& operator>>(QDataStream& stream, Rekord& r) {
stream >> r.imie;
stream >> r.nazwisko;
stream >> r.nazwa_wyd;
stream >> r.data_wyd;
stream >> r.przypomnienie;
return stream;
}


definicje_globalne.h



#ifndef DEFINICJE_GLOBALNE_H
#define DEFINICJE_GLOBALNE_H
#include <QtGui>
#include <QtSql>
#include "rekord.h"

bool createFile(QFile& dbFile) {
bool flag = true;
if(dbFile.open(QIODevice::WriteOnly)) {
QSqlDatabase dbRead = QSqlDatabase::addDatabase("QMYSQL");
dbRead.setHostName("localhost");
dbRead.setDatabaseName("wydarzenia");
dbRead.setUserName("user");
dbRead.setPassword("password");
bool dbReadOk = dbRead.open();
if(dbReadOk) {
qDebug() << "Baza danych wydarzenia otwarta"; // The database wydarzenia is open
QList<Rekord> dbStore;
QSqlQuery dbReadQr("SELECT osoby.imie,osoby.nazwisko,nazwa_wydarzenia.nazwa,w ydarzenia.data_wyd,wydarzenia.przypomnienie FROM osoby,nazwa_wydarzenia,wydarzenia WHERE wydarzenia.osoba=osoby.ID AND wydarzenia.wydarzenie=nazwa_wydarzenia.ID;");
if(dbReadQr.isActive()) {
qDebug() << "Zapytanie do bazy wydarzenia OK"; // "The query to database wydarzenia is active"
while(dbReadQr.next()) {
Rekord dbRekord(
dbReadQr.value(0).toString(),
dbReadQr.value(1).toString(),
dbReadQr.value(2).toString(),
dbReadQr.value(3).toDateTime(),
static_cast<qint16>(dbReadQr.value(4).toInt())
);
dbStore.append(dbRekord);
}
QDataStream stream(&dbFile);
stream << dbStore;
} else {
qDebug() << "Blad zapytania do bazy danych wydarzenia"; // Cannot send a query to the database wydarzenia
flag = false;
} // if(dbReadQr.isActive())
dbRead.close();
qDebug() << "Baza danych wydarzenia zamknieta"; // The database wydarzenia is closed
} else {
qDebug() << "Blad otwarcia bazy wydarzenia"; // Cannot open the database wydarzenia
flag = false;
} // if(dbReadOk)
dbFile.close();
qDebug() << "Plik database zamkniety"; // The file database is closed
} else {
qDebug() << "Blad otwarcia pliku database"; // Cannot open the file database
qDebug() << dbFile.errorString();
flag = false;
} // if(dbFile.open(QIODevice::WriteOnly))
return flag;
}

bool testUpdate(const QString& fileName, bool& isUpdated) {
bool flag = true;
QFileInfo dbInfo(fileName);
QSqlDatabase dbStatus = QSqlDatabase::addDatabase("QMYSQL");
dbStatus.setHostName("localhost");
dbStatus.setDatabaseName("wydarzenia_status");
dbStatus.setUserName("user");
dbStatus.setPassword("password");
bool dbStatusOk = dbStatus.open();
if(dbStatusOk) {
qDebug() << "Baza danych wydarzenia_status otwarta."; // The database wydarzenia_status is open
QSqlQuery dbStatusQr("SELECT name,datetime FROM tables;");
if(dbStatusQr.isActive()) {
qDebug() << "Zapytanie do bazy wydarzenia_status OK"; // Active query to database wydarzenia_status
while(dbStatusQr.next()) {
dbInfo.lastModified() >= dbStatusQr.value(1).toDateTime() ? isUpdated = true : isUpdated = false;
}
} else {
qDebug() << "Blad zapytania do bazy danych wydarzenia_status"; // Cannot send a query to the database wydarzenia_status
flag = false;
} // if(dbStatusQr.isActive())
} else {
qDebug() << "Blad otwarcia bazy danych wydarzenia_status"; // Cannot open the database wydarzenia_status
flag = false;
} // if(dbStatusOk)
dbStatus.close();
qDebug() << "Baza danych wydarzenia_status zamknieta"; // "The database <wyd...> is closed"
return flag;
}

#endif // DEFINICJE_GLOBALNE_H


Added after 12 minutes:

amleto
30th August 2012, 23:11
please only try to tackle one problem in a thread, otherwise there will be lots of cross-talk. Do you want to discuss seg fault issue or compiler issue?

ZikO
31st August 2012, 00:41
Hi,

Well. Both are important but I would really like to understand what I did wrong that compiler reports error.

Thnks for answer.

ChrisW67
31st August 2012, 01:13
At the top of rekord.cpp:


#include <QDataStream>


rekord.h only includes a forward declaration of QDataStream (through QtGlobal) that is enough to support the declarations you make there.

ZikO
31st August 2012, 03:10
At the top of rekord.cpp:


#include <QDataStream>


rekord.h only includes a forward declaration of QDataStream (through QtGlobal) that is enough to support the declarations you make there.
Hi Chris,
Thanks for your help. I cannot believe I've missed that line -.- I feel awkward.
I included it as you have specified but I am sorry I did not really understand what you were saying with regard to rekord.h. and QGlobal. Though, I assumed I needed to put this line


#include <QDataStream>

in rekord.cpp. because, apart from declarations in QGlobal, I would also need definitions from QDataStream.

Anyway, the application's working :)

ChrisW67
31st August 2012, 03:37
When compiling rekord.cpp the compiler first includes rekord.h and then processes the remainder of the cpp file. Your declaration of the two Rekord stream operators in the header requires only a forward declaration of QDataStream because they are only references (or pointers) to a QDataStream object. In your case, perhaps by accident rather than design, this is provided by the QtGlobal header you include. By the time the compiler gets to your definition of Rekord streaming operators the compiler needs a full prototype for QDataStream and its streaming functions and does not have it. The streaming operators for QString and QDateTime are in the headers for those classes, so they compiled fine. The prototype for the qint16 streaming operator is provided by the QDataStream header.

ZikO
31st August 2012, 12:59
Hi Chris,

Thanks for this great piece of knowledge :). Now, I understand what has happened. I did not come acros the "forward declaration" term before and as I googled it I can follow your explanation now. QGlobal was not included by accident. I thought it was needed by qint16 and any other platform independent types. I found it in Qt Documentation.

ChrisW67
31st August 2012, 23:33
QtGlobal includes a typedef for qint16 either directly or indirectly (I don't have Qt on this iPad to check). I suspect that including almost any Qt header indirectly includes QtGlobal anyway.