Koncepcja DataModule

0

Dla każdej jednostki potrzebuje unitu, w którym będę przechowywać różne wspólne dane np. menedżer BD.
W Delphi mamy do tego DataModule i tu coś w ten deseń chciałem zrobić:

#ifndef DM_H
#define DM_H

#include <QtSql\QtSql>

namespace Utility
{
	class DataModule
	{
	public:
		QSqlDatabase db;
		DataModule();
		~DataModule();
	};

	DataModule DM;
}


#endif
#include "DM.h"

using namespace Utility;

DataModule::DataModule()
{  
	db = QSqlDatabase::addDatabase("QMYSQL");
	db.setDatabaseName("");
	db.setUserName("");
	db.setPassword("");
	db.setHostName("");
	db.open();
}


DataModule::~DataModule()
{
}
#ifndef FIRMA_H
#define FIRMA_H

#include <QtGui/QMainWindow>
#include <QtSql\QtSql>
#include "ui_FIRMA.h"

class Firma : public QMainWindow
{
	Q_OBJECT

public:
	Firma(QWidget *parent = 0, Qt::WFlags flags = 0);
	~Firma();

	public slots:
		void dosmoething();

private:
	Ui::MainWindow ui;
	QSqlQuery Q;
	
};

#endif // AD_H
#include "DM.h"
#include "FIRMA.h"
#include <QMessageBox>

using namespace Utility;

Firma::Firma(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags), Q(DM.db)
{
	ui.setupUi(this);
	connect(Firma::ui.btnSave, SIGNAL(clicked()), this, SLOT(dosmoething()));	
}

Firma::~Firma()
{

}

void Firma::dosmoething()
{
}

Jak ominąć skutek wielokrotnego dołączania ?
Trochę jestem teoretyk, sądziłem że do tego wystarczy strażnik dołączania :)

VS2010 mówi
Error 1 error LNK2005: "class Utility::DataModule Utility::DM" (?DM@Utility@@3VDataModule@1@A) already defined in DM.obj

Jak wywalę includa w Firma.cpp to wtedy jest OK.

0

Zdefiniowałeś obiekt globalny:

DataModule DM;

Kłania się słówko extern ew. static...

http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
http://www.learncpp.com/cpp-tutorial/42-global-variables/

0

Static być nie może. Pisałem że jeden i ten sam obiekt - dostępny dla wszystkich.
Dałem extern DataModule DM w pliku nagłówkowym a w cpp jego definicję DataModule DM i linker się czepia że nie może znaleźć definicji.... Jak to poprawnie w końcu zrobić ?

0

Singleton?

0

Dziwne, bo singletona (jeden obiekt dla wszystkich) robi się właśnie przy pomocy static...

Zajrzyj tutaj:
http://www.cs.utexas.edu/users/downing/publications/Globals-JOOP-1996.pdf
(na końcu jest najlepsze rozwiązanie)

0

zrobiłem takiego singletona.

#ifndef DM_H
#define DM_H

#include <QtSql\QtSql>

namespace Utility
{
	class DataModule
	{
	private:
		DataModule(const DataModule&);
	public:
		QSqlDatabase db;
		DataModule();
		~DataModule();
		static DataModule& Instance();
	};
}


#endif

I potem sobie QSqlQuery inicjuje poprzez

Q(DataModule::Instance().db)

Czy taka koncepcja już jest OK ?
@Vpiotr, te z Pdfa trochę zakręcone mi się wydają w stosunku do tego co mi potrzebne : >

0

Bardziej:

#ifndef DM_H
#define DM_H
 
#include <QtSql\QtSql>
 
namespace Utility
{
        class DataModule
        {
        private:
                DataModule();
        public:
                QSqlDatabase db;
                ~DataModule();
                static DataModule& Instance();
        };
}
 
 
#endif
0

Wersja ze wskaźnikiem umożliwia wykrycie próby powtórnego utworzenia obiektu.

@maciejmt: rzeczywiste singletony są bardziej wykręcone :)

coś po krótce pod twój przykład (pisane na sucho):

        
// DataModule.h
class DataModule
        {
        public:
                DataModule();
                ~DataModule();
               static DataModule &getInstance();
               QSqlDatabase &getDb();
        private:
                QSqlDatabase db;
                static DataModule *instance;               
        };
        
// DataModule.cpp
// tu mogłem coś pokręcić
static DataModule *DataModule::instance = NULL;               

DataModule::DataModule() {
  if (instance == NULL) {
    instance = this;
  } 
}

DataModule::~DataModule() {
  if (instance == this) {
    instance = NULL;
  } 
}

DataModule &DataModule::getInstance()
{
  return *instance;
}

QSqlDatabase &DataModule::getDb()
{
  return db;
}
        
// użycie:
Q(DataModule::getInstance().getDb())
0

A nie łatwiej:

DataModule &DataModule::getInstance()
{
  static DataModule instance;
  return instance;
}
0

No mam tak jak wyżej i wydaje się działać cacy.
Generalnie do tego co pisałem w 1 poście wystarczyło tylko opakować w static, czyli te 4 linijki i wsio.

0

Hmmm o ile te moduły nie mają pracować na różnych bazach danych,to lepiej zrób sobie coś takiego co używam we wszystkich moich programach korzystających z bazy danych:

class DatabaseAccessor : public QObject
{
    static DatabaseAccessor *instance;
	QSqlDatabase base;

	DatabaseAccessor(QObject *parent=0);
    
public:	
	QSqlQuery query;

	static DatabaseAccessor* getInstance(void);
};

i cpp:

DatabaseAccessor::DatabaseAccessor(QObject *parent):QObject(parent)
{
	QSqlDatabase::addDatabase("QSQLITE");	
	base=QSqlDatabase::database();
	//in the future this path shoud be taken from options-in case of other cardgames support
	base.setDatabaseName("Databases/Magic/cards.db");
	if(!base.open())
	{
		QMessageBox::warning(NULL,tr("Error during opening cards' database!"),base.lastError().text(),QMessageBox::Ok);
		exit(0);
	}
           query=QSqlQuery(base);
}
DatabaseAccessor* DatabaseAccessor::getInstance(void)
{
	if(!instance) instance=new DatabaseAccessor();
	return instance;
}

Używasz potem tylko DatabaseAccessor::getInstance()->query do tworzenia zapytań do bazy

0
winerfresh napisał(a)

A nie łatwiej:

DataModule &DataModule::getInstance()
{
  static DataModule instance;
  return instance;
}

Oczywiście łatwiej - jeśli nie musisz inicjować obiektu z parametrami.

1 użytkowników online, w tym zalogowanych: 0, gości: 1