Please help..
I have singleton class but can't get it's instance.
dbinfogetterdao.h
#ifndef MATRIXGETTERDAO_H
#define MATRIXGETTERDAO_H
#include <QtSql/QSqlDatabase>
namespace Ui{
class DBInfoGetterDAO;
}
class DBInfoGetterDAO
{
public:
static DBInfoGetterDAO& getInstance();
private:
DBInfoGetterDAO();
DBInfoGetterDAO(DBInfoGetterDAO const&);
void operator=(DBInfoGetterDAO const&);
};
#endif // MATRIXGETTERDAO_H
dbinfogetterdao.cpp
#include "dbinfogetterdao.h"
#include <QtSql/QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QSqlQuery>
DBInfoGetterDAO& DBInfoGetterDAO::getInstance()
{
static DBInfoGetterDAO instance;
return instance;
}
DBInfoGetterDAO::DBInfoGetterDAO()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("mdpschema");
db.setUserName("root");
db.setPassword("password");
bool ok = db.open();
qDebug() << "db connection status = " << ok;
QSqlError error = db.lastError();
if (ok == false){
qDebug() << "error text = " + error.text();
}
}
I create instance like this:
DBInfoGetterDAO dbInfoGetterDAO = DBInfoGetterDAO::getInstance();
Please could you explain me what I did wrong.
your constructor is private, so you cannot create an object of your class.
It seems that getInstance() method declaration is different from its definition, just change
static DBInfoGetterDAO getInstance();
into
static DBInfoGetterDAO& getInstance();
Also move class definition and class methods definitions inside Ui namespace as yo did with class forward declaration.
You are doing it fundamentally wrong. This is not the correct way of defining singletons with Qt. I would suggest to use QGlobalStatic instead.
Instead of doing all this, you could simply do this:
Q_GLOBAL_STATIC(MyType, staticType)
Moreover, your singleton is as racey as possible. It will blow up from different threads all of a sudden.
I added namespace 'DB' to dbinfogetterdao.h:
namespace DB {
namespace Ui{
class DBInfoGetterDAO;
}
class DBInfoGetterDAO
{
public:
static DBInfoGetterDAO& getInstance();
void printAllCountries();
QList<QString> getAppropriateCountriesFromDB(QString property, QString site_type);
Flightmatrix getFlightMatrix(QString site_type);
static void printFlightMatrix(QVector< QVector< int > > matrix);
private:
DBInfoGetterDAO();
DBInfoGetterDAO(DBInfoGetterDAO const&);
void operator=(DBInfoGetterDAO const&);
int getIndexByName(QHash<int, QString> map, QString name);
};
}
and in dbinfogetterdao.cpp I've added 'using namespace DB':
using namespace DB;
DBInfoGetterDAO& DBInfoGetterDAO::getInstance()
{
static DBInfoGetterDAO instance;
return instance;
}
DBInfoGetterDAO::DBInfoGetterDAO()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("mdpschema");
db.setUserName("root");
db.setPassword("password");
bool ok = db.open();
qDebug() << "db connection status = " << ok;
QSqlError error = db.lastError();
if (ok == false){
qDebug() << "error text = " + error.text();
}
}
it helped me.
the problem is not in the singleton implementation or due to namespace
it is here
DBInfoGetterDAO dbInfoGetterDAO = DBInfoGetterDAO::getInstance();
DBInfoGetterDAO dbInfoGetterDAO is trying to create object using private constructors.
Related
I try to get a QObject-subclassed object from a Qt shared library to a Qt application dynamically.
I have tried to apply a previous answer about this subject : QLibrary - import a class
Here is my common interface tabappinterface.h:
#ifndef TABAPP_H
#define TABAPP_H
#include <QObject>
#include <QWidget>
class TabAppInterface : public QObject
{
Q_OBJECT
public:
virtual ~TabAppInterface()
{
}
QWidget *app;
QString title;
};
#endif // TABAPP_H
My class dll-side mytabapp.h:
#ifndef MYTAB_H
#define MYTAB_H
#include "tabapp_global.h"
#include "tabappinterface.h"
class MYTABSHARED_EXPORT MyTabApp: public TabAppInterface
{
public:
MyTabApp();
virtual ~MyTabApp();
QWidget *app;
QString title;
};
extern "C" MYTABSHARED_EXPORT TabAppInterface *getTabApp();
and its implementation mytabapp.cpp:
#include "mytabapp.h"
MyTabApp::MyTabApp()
{
app = new AppWidget();
title = QStringLiteral("My Tab App");
}
MyTabApp::~MyTabApp()
{
}
TabAppInterface *getTabApp()
{
return new MyTabApp();
}
My app-side implementation:
void ContainerMainWindow::loadLibraries()
{
QLibrary myLib("mytabapp.dll");
if(myLib.isLoaded())
{
qDebug() << "Loaded!";
}
typedef TabAppInterface *(*tabAppGetProt)();
auto tabAppGetter = (tabAppGetProt) myLib.resolve("getTabApp");
if(tabAppGetter)
{
auto *tabApp = tabAppGetter(); // not null
qDebug() << tabApp->title; // print empty string
qDebug() << (QWidget *)(tabApp->app); // SEGFAULT
}
}
As stated in comment in the last lines, the object members are not retrieved although tabApp is not null.
Any idea?
Thanks!
You're accessing the base class variables (fields) title and app, which nobody ever initialized. These variables aren't virtual at all, so those in the derived class just hide those in the base class. As a solution, you can declare them as protected in the base class and encapsulate them in getters and setters.
This way, your base class is like:
class TabAppInterface : public QObject
{
Q_OBJECT
public:
virtual ~TabAppInterface(){}
QWidget *getApp() const { return app; }
void setApp(QWidget *value) { app = value; }
QString getTitle() const { return title; }
void setTitle(const QString &value) { title = value; }
protected:
QWidget *app;
QString title;
};
and the derived class is just like:
class MYTABSHARED_EXPORT MyTabApp: public TabAppInterface
{
public:
MyTabApp();
virtual ~MyTabApp();
};
You can still directly access the variables inside the derived class (i.e. initialize them in constructor) and through the getters/setters methods from outside:
auto *tabApp = tabAppGetter();
qDebug() << tabApp->getTitle();
qDebug() << tabApp->getApp();
For a c++ application which I'm currently being busy to develop, I have several classes which I need to access through my entire code, without creating a new object
So searching I have found that one of methods that can be used is with the extern linkage specifier.
I would like to know what is best way to use this extern method, I wrote a little sample code
classone.h
#ifndef CLASSONE_H
#define CLASSONE_H
class ClassOne
{
public:
ClassOne();
void showClassOneInt();
private:
int m_classOneInt;
};
extern ClassOne *classOne;
---------------------------------------
classone.cpp
#include "classone.h"
#include <QDebug>
ClassOne *classOne;
ClassOne::ClassOne()
{
m_classOneInt = 1;
}
void ClassOne::showClassOneInt()
{
qDebug() << "ClassOneInt: " << m_classOneInt;
}
---------------------------------------
classtwo.h
#ifndef CLASSTWO_H
#define CLASSTWO_H
class ClassTwo
{
public:
ClassTwo();
void showClassTwoInt();
private:
int m_classTwoInt;
};
#endif // CLASSTWO_H
---------------------------------------
classtwo.cpp
#include "classtwo.h"
#include <QDebug>
ClassTwo::ClassTwo()
{
m_classTwoInt = 2;
}
void ClassTwo::showClassTwoInt()
{
qDebug() << "ClassTwoInt: " << m_classTwoInt;
}
---------------------------------------
classthree.h
#ifndef CLASSTHREE_H
#define CLASSTHREE_H
class ClassThree
{
public:
ClassThree();
void showClassThreeInt();
private:
int m_classThreeInt;
};
#endif // CLASSTHREE_H
---------------------------------------
classthree.cpp
#include "classthree.h"
#include <QDebug>
ClassThree::ClassThree()
{
m_classThreeInt = 3;
}
void ClassThree::showClassThreeInt()
{
qDebug() << "ClassThreeInit: " << m_classThreeInt;
}
---------------------------------------
classtest.cpp
#include "classtest.h"
#include "classone.h"
#include "classtwo.h"
#include "classthree.h"
//Class one pointer already in header
//Class two
extern ClassTwo *classTwo;
//Class three
extern ClassThree *classThree;
ClassTest::ClassTest()
{
//Execute class one
classOne->showClassOneInt();
//Execute class two
classTwo->showClassTwoInt();
//Execute class three
classThree->showClassThreeInt();
}
---------------------------------------
main.cpp
#include <QCoreApplication>
#include "classone.h"
#include "classtwo.h"
#include "classthree.h"
#include "classtest.h"
//Class one pointer already in header file
//Class two pointer
ClassTwo *classTwo;
//Class three pointer
ClassThree *classThree;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//Create object for class one
classOne = new ClassOne;
//Create object for class two
classTwo = new ClassTwo;
//Create object for class three
ClassThree three;
classThree = &three;
//Create a classTest object
ClassTest test;
return a.exec();
}
Please could you tell me what is the best way, thanks for you help.
The best way is to not do it and instead use dependency injection.
If you choose to do it anyway, you should at least use getter/factory functions (i.e. ClassOne &getClassOne())) so you can:
be sure random code can't change the objects and
handle order of construction implicitly by constructing on first use (sometimes appropriate, sometimes not).
Having a global state is generally not a great idea, seek to eliminate it.
If that cannot be done, try the singleton pattern.
class Singleton
{
Singleton(); //keep constructors private to avoid creation by others
static Singleton inst;
public:
static Singleton& Instance() {return inst;}
};
Singleton Singleton::inst;
I'm trying to implement a State Pattern in C++, but have problems with the circular dependency. I have read other related material here - unfortunately it didn't help me. I don't have a lot of experience with C++, so bear with me.
The following code is developed on a Ubuntu 10.10 machine in Eclipse Helios CDT:
ConcreteSystem.h
#ifndef CONCRETESYSTEM_H_
#define CONCRETESYSTEM_H_
class SystemState;
class ConcreteSystem {
public:
ConcreteSystem();
void SelfTestFailed();
void Restart();
private:
friend class SystemState;
SystemState *currentState;
void ChangeState(SystemState *state);
};
#endif /* CONCRETESYSTEM_H_ */
ConcreteSystem.cpp
#include "ConcreteSystem.h"
#include "SystemState.h"
ConcreteSystem::ConcreteSystem() {
currentState = SelfTest::GetInstance();
}
void ConcreteSystem::SelfTestFailed() {
currentState->SelfTestFailed(this);
}
void ConcreteSystem::Restart() {
currentState->Restart(this);
}
void ConcreteSystem::ChangeState(SystemState *state){
currentState = state;
}
SystemState.h
#ifndef SYSTEMSTATE_H_
#define SYSTEMSTATE_H_
class ConcreteSystem;
class SystemState {
public:
virtual void Restart(ConcreteSystem *cs);
virtual void SelfTestFailed(ConcreteSystem *cs);
protected:
virtual void ChangeState(ConcreteSystem *cs, SystemState *state);
};
#endif /* SYSTEMSTATE_H_ */
SystemState.cpp
#include "SystemState.h"
#include "ConcreteSystem.h"
void SystemState::Restart(ConcreteSystem *cs) {
}
void SystemState::SelfTestFailed(ConcreteSystem *cs) {
}
void SystemState::ChangeState(ConcreteSystem *cs, SystemState *state) {
cs->ChangeState(state);
}
SelfTest.h
#ifndef SELFTEST_H_
#define SELFTEST_H_
#include "SystemState.h"
class SelfTest : public SystemState {
public:
SelfTest();
void SelfTestFailed(ConcreteSystem* cs);
static SystemState* GetInstance();
private:
static SystemState* instance;
};
#endif /* SELFTEST_H_ */
SelfTest.cpp
#include "SelfTest.h"
#include "Failure.h"
SystemState* SelfTest::instance = 0;
SelfTest::SelfTest() {
}
void SelfTest::SelfTestFailed(ConcreteSystem *cs) {
ChangeState(cs, Failure::GetInstance());
}
SystemState* SelfTest::GetInstance() {
if (instance == 0) {
instance = new SelfTest();
}
return instance;
}
Failure.h
#ifndef FAILURE_H_
#define FAILURE_H_
#include "SystemState.h"
class SelfTest;
class Failure : public SystemState {
public:
Failure();
void Restart(ConcreteSystem* t);
static SystemState* GetInstance();
private:
static SystemState* instance;
};
#endif /* FAILURE_H_ */
Failure.cpp
#include "Failure.h"
#include "SelfTest.h"
SystemState* Failure::instance = 0;
Failure::Failure() {
}
void Failure::Restart(ConcreteSystem* t) {
ChangeState(t, SelfTest::GetInstance());
}
SystemState* Failure::GetInstance() {
if (instance == 0) {
instance = new Failure();
}
return instance;
}
I have problem with the includes, which gives me some weird compiler errors. Anyone with a good solution to this problem?
From the looks of the code you've posted, you'll have classes being redefined. Looking at your Failure.cpp file, you have:
#include "Failure.h"
#include "SelfTest.h"
Which will include both of those files, and each of those files include the SystemState.h file. Since the SystemState.h file is included more than once, it tries to redefine the SystemState class. At the top of each of your header files, you should do something like this:
// SystemState.h
#ifndef SystemState_h
#define SystemState_h
.. class definition ..
#endif // close the if statement from above.
As an aside on the design, I think it's bad form for the states to know about each other - use your ConcreteSystem as a state controller and then base the state on the return value of the last state operation.
Also, if you're relatively inexperienced with C++, I would recommend looking at this as a great source of learning material (in addition to StackOverflow, of course!).
I'm having a static linking problem in my C++ app. I'm hoping you can help. Code for header and source below.
#ifndef PRACTICARDSDB_H
#define PRACTICARDSDB_H
#include "cardset.h"
#include "card.h"
#include "filter.h"
class PractiCardsDB
{
public:
PractiCardsDB();
static void resetAll();
static void resetDates();
static CardSet getCardSet();
static CardSet getCardSet(Filter filter);
static void addCard(Card card);
static void editCard(Card card);
static void deleteCard(Card card);
static bool createConnection();
};
#endif // PRACTICARDSDB_H
Above is the header file and below is the source file.
#include "practicardsdb.h"
#include <QtSql/QSqlDatabase>
#include <QMessageBox>
PractiCardsDB::PractiCardsDB() {}
static bool PractiCardsDB::createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("EnglishSpanish");
if (!db.open())
{
return false;
}
return true;
}
The error I receive is: cannot declare member function 'static bool PractiCardsDB::createConnection()' to have static linkage. Any help?
I'm using Qt 4.7 with C++ inside Qt Creator if it helps.
When you define a static member function separately from the declaration, you do not have to use the static modifier.
bool PractiCardsDB::createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("EnglishSpanish");
if (!db.open())
{
return false;
}
return true;
}
Also do you really mean to make every single function of your class static? Your class represents a database of sorts for Card objects, so I think you'd want to actually store member data with the class itself?
Even in that snippet above, you create a QSqlDatabase object, but db's existence is only the extent of the createConnection() function.
Remove static decleration from your cpp file, it should only be in the header file. Like:
bool PractiCardsDB::createConnection()
{
....
}
With the following code :
class DBConnection
{
// Methodes : private
private:
// Constructeur
DBConnection();
// Destructeur
~DBConnection();
// Methodes : public
public:
bool open();
bool close();
// Methodes : public : static
public:
static DBConnection * getSingleton();
// Variables
private:
static DBConnection * singleton;
QSqlDatabase conn;
QString driver,
host,
userName,
password,
DBName;
};
#endif // DBCONNECTION_HPP
#include "DBConnection.hpp"
// Initialisation du singleton dans l'espace global, car static
DBConnection * DBConnection::singleton = 0;
// Methodes : private
DBConnection::DBConnection() {
this->conn = QSqlDatabase::addDatabase("QMYSQL");
this->conn.setHostName("");
this->conn.setUserName("");
this->conn.setPassword("");
this->conn.setDatabaseName("");
}
DBConnection::~DBConnection(){};
// Methodes : public
bool DBConnection::open() {
bool rep = this->conn.isOpen()?true:this->conn.open();
if(!rep)
QMessageBox::critical(0, "Erreur critique !", "Impossible d'ouvrir la base de données !");
return rep;
}
DBConnection * DBConnection::getSingleton() {
if(singleton == 0)
singleton = new DBConnection;
return singleton;
}
#ifndef DAOMYSQLFACTORY_HPP
#define DAOMYSQLFACTORY_HPP
#include "InterfaceDAOFactory.hpp"
#include "DAO.hpp"
class DAOMySQLFactory : public InterfaceDAOFactory
{
// Methodes : private
private:
// Constructeur
DAOMySQLFactory();
// Destructeur
~DAOMySQLFactory();
// Methodes : public : heritées
public:
DAO * getDAOClient();
DAO * getDAOSite();
DAO * getDAOMachine();
// Methode : static
public:
static DAOMySQLFactory * getSingleton();
// Variables
private:
// Instance unique
static DAOMySQLFactory * singletonMySQLFactory;
};
#endif // DAOMYSQLFACTORY_HPP
#include "DAOMySQLFactory.hpp"
#include "DBConnection.hpp"
#include "DAOMySQLClient.hpp"
DAOMySQLFactory * DAOMySQLFactory::singletonMySQLFactory = 0;
// Methodes : private
// Constructeur
DAOMySQLFactory::DAOMySQLFactory() {}
// Destructeur
DAOMySQLFactory::~DAOMySQLFactory() {}
// Methode : static
DAOMySQLFactory * DAOMySQLFactory::getSingleton() {
if(singletonMySQLFactory == 0)
singletonMySQLFactory = new DAOMySQLFactory;
return singletonMySQLFactory;
}
// Methodes : public : heritee
DAO * DAOMySQLFactory::getDAOClient() {
return 0;
}
...
#include <QApplication>
#include "WinMain.h"
//TEST
#include "DAOPersistenceFactory.hpp"
#include "DAO.hpp"
#include "DAOMySQLFactory.hpp"
#include "DBConnection.hpp"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
//TEST
InterfaceDAOFactory * idao = DAOPersistenceFactory::getDAOFactory(DAOPersistenceFactory::MySQL);
DAO * d = idao->getDAOClient();
DBConnection::getSingleton();
WinMain fen;
fen.show();
return app.exec();
}
#ifndef DAO_HPP
#define DAO_HPP
#include <QString>
#include <QStringList>
#include <QSqlQuery>
class DAO {
// Methodes : public
public:
DAO();
virtual ~DAO();
// Methodes : public : abstraites
public:
virtual QStringList findAll() = 0;
// Variable
protected:
QSqlQuery allQuery;
};
#endif // DAO_HPP
#include "DAO.hpp"
DAO::DAO() {}
DAO::~DAO(){}
#ifndef DAOMYSQLCLIENT_HPP
#define DAOMYSQLCLIENT_HPP
#include <QString>
#include <QStringList>
#include <QSqlQuery>
#include "DAO.hpp"
#include "DBConnection.hpp"
class DAOMySQLClient : public DAO
{
// Methodes : public
public:
DAOMySQLClient();
// DAOMySQLClient(DBConnection * connection);
//Variables
private:
DBConnection * conn;
QSqlQuery byIdQuery,
byNameQuery;
};
#endif // DAOMYSQLCLIENT_HPP
#include <QMessageBox>
#include <QSqlError>
#include <QVariant>
#include "DAOMySQLClient.hpp"
// Methodes : public
// Constructeur
DAOMySQLClient::DAOMySQLClient() {}
// Constructeur
// DAOMySQLClient::DAOMySQLClient(DBConnection * connection) {
// this->conn = connection;
// this->conn->open();
// initQueries();
// }
...
Why i have a
undefined reference to 'DBConnection::getSingleton()'
collect2:ld returned 1 exit status
in main() and DAOPersistenceFactory::getDAOFactory(DAOPersistenceFactory::MySQL); not whereas it seems to have the same implementation ?
I have the feeling that you forgot to add DBConnection.cpp to your .pro file.
If you did, try re-running qmake. Also try to make clean.
I had lots of weird issues with out-of-date object files in the past. ;)