Forum » Programiranje » [Qt/C++]problem z Undefined reference na konstanti znotraj razreda
[Qt/C++]problem z Undefined reference na konstanti znotraj razreda
KernelPanic ::
Imam sledec razred:
in njegovo implementacijo:
V .cpp datoteki mi v vrsitci (v metodi roleNames())
Zakaj za vraga?!
Lp,
Marko
#ifndef UEPEOPLEMODEL_H #define UEPEOPLEMODEL_H #include <QImage> #include <QVariant> #include <QStringList> #include <QDebug> #include <QHash> #include <QByteArray> #include <QtSql/QSqlError> #include <QtSql/QSqlQueryModel> #include <QtSql/QSqlRecord> #include <QModelIndex> #include <QQuickImageProvider> #include "../settings/uedefaults.h" #include "../settings/uetypes.h" class UePeopleModel : public QSqlQueryModel, QQuickImageProvider { Q_OBJECT public: UePeopleModel(QObject *parent=0); ~UePeopleModel(); QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; QImage image(const QString &id) const; QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize); UeTypeRoles roleNames() const; public: static const int UePersonNameRole=0x101;//Qt::UserRole+1;/*0x0101;*/ //static const int UePersonImageRole=UePersonNameRole+1;/*0x0102;*/ //static const int UePersonImageRole=Qt::UserRole+2; }; #endif // UEPEOPLEMODEL_H
in njegovo implementacijo:
#include "uepeoplemodel.h" UePeopleModel::UePeopleModel(QObject* parent) : QSqlQueryModel(parent), QQuickImageProvider(QQmlImageProviderBase::Image, QQmlImageProviderBase::ForceAsynchronousImageLoading) { QSqlDatabase db; if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE, Qt::CaseInsensitive)) { db=QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER, UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE); } // if db.setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME); db.setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME); db.setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME); db.setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD); if(db.open()) { this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE, db); } else { qDebug() << db.lastError().text(); } } // default constructor UePeopleModel::~UePeopleModel() { } // default destructor QVariant UePeopleModel::data(const QModelIndex &index, int role) const { QVariant value=QSqlQueryModel::data(index, role); if(value.isValid()) { switch(role) { case UePeopleModel::UePersonNameRole: { return value.toString(); } // case /* case UePeopleModel::UePersonImageRole: { return QString::number(index.row()); } // case */ default: value=QVariant(); } // switch } // if return value; } // data QImage UePeopleModel::image(const QString &id) const { int iRow=id.toInt(); } // image QImage UePeopleModel::requestImage(const QString &id, QSize *size, const QSize &requestedSize) { QImage image=this->image(id); *size = image.size(); return image; } // requestImage UeTypeRoles UePeopleModel::roleNames() const { UeTypeRoles roles; roles.insert(UePersonNameRole, "UePersonNameRole"); /* roles.insert("UePersonImageRole", UePersonNameRole); */ return roles; } // roleNames
V .cpp datoteki mi v vrsitci (v metodi roleNames())
roles.insert(UePersonNameRole,javi napako:
"UePersonNameRole");
uepeoplemodel.cpp:87: error: undefined reference to `UePeopleModel::UePersonNameRole'
Zakaj za vraga?!
Lp,
Marko
- spremenil: KernelPanic ()
Jeremias ::
Na hitro. Predvidevam da tvoja funkcija deklarirana kot UeTypeRoles::insert(const int &type, String &name) oz. nekaj podobnega. No problem pri tebi je, da funkcija za prvi parameter pričakuje referenco, ker pa ti imaš UePersonNameRole spremenljivko deklarirano kot static (katero kompajler zamenja z dejansko vrednostjo ob prevajajnju) ti ne more podat kot referenco in zaradi tega dobiš error. Možnosti imaš tu dve, umakneš static od spremenljivke ali pa enostavno spremeniš funkcijo insert da sprejema int namesto referenco na int.
Lp
Jernej
Jernej
KernelPanic ::
Na hitro. Predvidevam da tvoja funkcija deklarirana kot UeTypeRoles::insert(const int &type, String &name) oz. nekaj podobnega. No problem pri tebi je, da funkcija za prvi parameter pričakuje referenco, ker pa ti imaš UePersonNameRole spremenljivko deklarirano kot static (katero kompajler zamenja z dejansko vrednostjo ob prevajajnju) ti ne more podat kot referenco in zaradi tega dobiš error. Možnosti imaš tu dve, umakneš static od spremenljivke ali pa enostavno spremeniš funkcijo insert da sprejema int namesto referenco na int.
Funkcija pricakuje navaden int, drugi parameter je QByteArray:
UeTypeRoles UePeopleModel::roleNames() const { UeTypeRoles roles; roles.insert(0x0101, "UePersonNameRole"); roles.insert(0x0102, "UePersonImageRole"); return roles; } // roleNames
UeTypeRoles je pa deklariran kot:
typedef QHash<int, QByteArray> UeTypeRoles;Ze veckrat sem konstante znotraj razreda deklariral kot static constpa nikoli nisem imel tezav in mi ni jasno, v cem je fora!
windigo ::
Tako, kot so ti napisali: QHash::insert(const Key & key, const T & value) jemlje reference, ne vrednosti, kompajler pa reference sploh nima, ker se je pisec kompajlerja odločil, da bo v takem primeru povsod po kodi raje vstavil neposredno vrednost in ne bo alociral prostora za statično spremenljivko (saj gre za konstanto), tukaj zato ne more narediti reference.
Workaround je simpl:
const int myRole = UePersonRoleName;
roles.insert(myRole, "bla bla");
Workaround je simpl:
const int myRole = UePersonRoleName;
roles.insert(myRole, "bla bla");
KernelPanic ::
Tako, kot so ti napisali: QHash::insert(const Key & key, const T & value) jemlje reference, ne vrednosti, kompajler pa reference sploh nima, ker se je pisec kompajlerja odločil, da bo v takem primeru povsod po kodi raje vstavil neposredno vrednost in ne bo alociral prostora za statično spremenljivko (saj gre za konstanto), tukaj zato ne more narediti reference.
Workaround je simpl:
const int myRole = UePersonRoleName;
roles.insert(myRole, "bla bla");
AAAA, torej tukaj sploh ni tezava v deklaraciji static const memberja znotraj razreda! Bom sedaj se malo potuhtal, se javim, kaj sem spacal! Hvala za obrazlozitev, sedaj sem se 1x pogledal funkcijo insert in da, jemlje reference, slamparija, slamparija ... :D
windigo ::
Če bi bil insert klican s parametri po vrednosti, bi se ob klicu ustvarile kopije objektov key in value. V primeru int in char * to ni poseben problem, pri kakšnem drugem objektu pa bi se klicali copy-konstruktorji in destruktorji, ali pa bi morda zasedli precej prostora na skladu. Da o morebitnih kasnejših problemih z identitetami niti ne govorim.
Zadeva s deklaracijami in definicijami razrednih statičnih konstant za int pa je zgodovinsko rahlo komplicirana (spreminjala se je do standarda do standarda), več o tem tukaj.
Zadeva s deklaracijami in definicijami razrednih statičnih konstant za int pa je zgodovinsko rahlo komplicirana (spreminjala se je do standarda do standarda), več o tem tukaj.
windigo ::
Btw,
out of class definicija
const int UePeopleModel::UePersonNameRole;
bi po mojem pomagala v skoraj vseh primerih.
out of class definicija
const int UePeopleModel::UePersonNameRole;
bi po mojem pomagala v skoraj vseh primerih.
KernelPanic ::
Tako, kot so ti napisali: QHash::insert(const Key & key, const T & value) jemlje reference, ne vrednosti, kompajler pa reference sploh nima, ker se je pisec kompajlerja odločil, da bo v takem primeru povsod po kodi raje vstavil neposredno vrednost in ne bo alociral prostora za statično spremenljivko (saj gre za konstanto), tukaj zato ne more narediti reference.
Workaround je simpl:
const int myRole = UePersonRoleName;
roles.insert(myRole, "bla bla");
Sem takole resil, kot si predlagal, hvala, sicer je malo grdo, ampak dela! :D
phantom ::
To je tudi odvisnocod kompajlerja. Clang konstante razreda (static const int) vstavi direktno, tudi kadar funkcija jemlje reference, in bi tvoja originalna koda delovala. GCC pa, če funkcija vzame referenco (četudi je const), konstanto pošlje kot referenco do konstante, torej jo moraš imeti definirano tudi v .cpp fajlu, isto kot static spremenljivko, drugače bo undefined reference.
~
~
:wq
~
:wq
Zgodovina sprememb…
- spremenil: phantom ()
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Qt/QML zajem podatkov iz podatkovne baze, dobim samo opise fieldov ter prazne vrednosOddelek: Programiranje | 1717 (1460) | windigo |
» | C++ problem: težava z hirerarhijo razredaOddelek: Programiranje | 1221 (1061) | fiction |
» | [VB2005PRO]DatabaseOddelek: Programiranje | 1011 (947) | darkolord |
» | [ C ] floating point not loaded !!?Oddelek: Programiranje | 1554 (1487) | Fizikalko |
» | [C++] for {}Oddelek: Programiranje | 1708 (1402) | Gundolf |