PDA

View Full Version : Question about singleton



SirJonas
22nd October 2016, 01:35
Hi i'm using singleton but i did samemitakes when i use singleton. Normally i create static object. But this is not recomendable.
So someine can help me with this code i need to do this:
First thing i am trying to make my _instance like a pointer. Second i am trying initialize it the first time instance is called.
Example for c++:

class GlobalClass
{
int m_value;
public:
GlobalClass(int v = 0)
{
m_value = v;
}
int get_value()
{
return m_value;
}
void set_value(int v)
{
m_value = v;
}
};

// Default initialization
GlobalClass *global_ptr = 0;

void foo(void)
{
// Initialization on first use
if (!global_ptr)
global_ptr = new GlobalClass;
global_ptr->set_value(1);
cout << "foo: global_ptr is " << global_ptr->get_value() << '\n';
}

void bar(void)
{
if (!global_ptr)
global_ptr = new GlobalClass;
global_ptr->set_value(2);
cout << "bar: global_ptr is " << global_ptr->get_value() << '\n';
}

int main()
{
if (!global_ptr)
global_ptr = new GlobalClass;
cout << "main: global_ptr is " << global_ptr->get_value() << '\n';
foo();
bar();
}

Some example similar for QT? I need some example very similiar to this example in c++.:confused:

ChrisW67
22nd October 2016, 08:58
Using Qt does not suddenly make C++ stop working. It does not matter whether GlobalClass is derived from a Qt class or not.

SirJonas
22nd October 2016, 11:03
for example first thing i am not doing my _instance like a pointer. And i dont initialize it the first time instance is called.
So i think this example that i did with instances is wrong.:confused:

Code:
#include <QCoreApplication>
#include <QDebug>
#include "downloader.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QObject::connect(Downloader::instance(),Downloader ::testSignal,
{
});
return a.exec();
}

downloader.cpp:
#include "downloader.h"
#include <QDebug>


Downloader &Downloader::instance()
{
Downloader _instance;
return _instance;
}

Downloader::Downloader(QObject *parent) : QObject(parent)
{
doSomething();
}

void Downloader::doSomething()
{
//emit testSignal();
qDebug() << "It's working!!!!";
QString s="http://myweb/currxml.php";
manager = new QNetworkAccessManager(this);
manager->get(QNetworkRequest(QUrl(s)));
emit instance().testSignal();
}

void Downloader::replyFinished (QNetworkReply *reply)
{
if(reply->error())
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
}
else
{
//qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toStrin g();
//qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDate Time().toString();
//qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULo ngLong();
//qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute ).toInt();
//qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribu te).toString();
QString p = reply->request().url().fileName();
QFile *file = new QFile("C:/Users/moh/"+p);
if(file->open(QFile::Append))
{
file->write(reply->readAll());
file->flush();
file->close();
}
delete file;
}

reply->deleteLater();
}

downloader.h:
#ifndef Downloader_H
#define Downloader_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QDateTime>
#include <QFile>
#include <QDebug>
class Downloader : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Downloader)
public:
Downloader &instance();
explicit Downloader(QObject *parent = nullptr);
QString s;
//virtual ~Downloader(){}

void doSomething();
signals:

void testSignal();

public slots:
//void testSlot();
void replyFinished (QNetworkReply *reply);

private:
QNetworkAccessManager *manager;

};

#endif // Downloader_H

anda_skoa
22nd October 2016, 16:57
Using a local static is a valid option for doing a singleton.

Again, as Chris67 already said, using Qt doesn't suddenly invalidate common C++ solutions.

Cheers,
_

ChrisW67
23rd October 2016, 01:31
Just a note on your Downloader::instance() function: it is returning a reference to a stack-based local variable. That local variable ceases to exist at the return of the function, invalidating the reference, and leading to undefined behaviour.

Take a look here for a way to do a singleton C++ class without pointers:
http://stackoverflow.com/questions/1008019/c-singleton-design-pattern#1008289

SirJonas
23rd October 2016, 02:43
when you say:
invalidating the reference, and leading to undefined behaviour.

you mean that the code is wrong?
Anyways i have one problem too because when i connect download my the file but only once time i call the signal

ChrisW67
24th October 2016, 21:29
you mean that the code is wrong?

Yes. A reference must always refer to an object that exists


Anyways i have one problem too because when i connect download my the file but only once time i call the signal

The signal is emitted once (on a second downloader instance at line 38) during the construction of the object at line 22. Then the downloader ceases to exist at line 23. At at least I think it would if the instance() function ever returned... I do not think it will in your code as the constructor constructs another local downloader, which constructs another, etc.