» »

[Qt/C++]problem z Undefined reference na konstanti znotraj razreda

[Qt/C++]problem z Undefined reference na konstanti znotraj razreda

KernelPanic ::

Imam sledec razred:
#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,
"UePersonNameRole");
javi napako:
uepeoplemodel.cpp:87: error: undefined reference to `UePeopleModel::UePersonNameRole'

Zakaj za vraga?!

Lp,
Marko

stapler rump ::

KernelPanic ::

stapler rump je izjavil:

Tole si preberi.
Sem ze prej, ampak v cem je fora?!

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

KernelPanic ::

Jeremias je izjavil:

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");

KernelPanic ::

windigo je izjavil:

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.

windigo ::

Btw,

out of class definicija

const int UePeopleModel::UePersonNameRole;

bi po mojem pomagala v skoraj vseh primerih.

KernelPanic ::

windigo je izjavil:

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

Zgodovina sprememb…

  • spremenil: phantom ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Qt/QML zajem podatkov iz podatkovne baze, dobim samo opise fieldov ter prazne vrednos

Oddelek: Programiranje
71736 (1479) windigo
»

C++ problem: težava z hirerarhijo razreda

Oddelek: Programiranje
141235 (1075) fiction
»

[VB2005PRO]Database

Oddelek: Programiranje
91016 (952) darkolord
»

[ C ] floating point not loaded !!?

Oddelek: Programiranje
111561 (1494) Fizikalko
»

[C++] for {}

Oddelek: Programiranje
291719 (1413) Gundolf

Več podobnih tem