Koncepcja DataModule

Odpowiedz Nowy wątek
2011-08-24 00:27
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" ([email protected]@@[email protected]@A) already defined in DM.obj

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

edytowany 2x, ostatnio: maciejmt, 2011-08-24 00:30

Pozostało 580 znaków

2011-08-24 11:29
0

Zdefiniowałeś obiekt globalny:

DataModule DM;

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

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

edytowany 1x, ostatnio: vpiotr, 2011-08-24 11:33

Pozostało 580 znaków

2011-08-24 13:25
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ć ?

Pozostało 580 znaków

2011-08-24 13:27
0

Singleton?

Pozostało 580 znaków

2011-08-24 13:41
0

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

Zajrzyj tutaj:
http://www.cs.utexas.edu/user[...]cations/Globals-JOOP-1996.pdf
(na końcu jest najlepsze rozwiązanie)

edytowany 2x, ostatnio: vpiotr, 2011-08-24 13:52

Pozostało 580 znaków

2011-08-24 14:21
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 : >

edytowany 1x, ostatnio: maciejmt, 2011-08-24 14:24

Pozostało 580 znaków

2011-08-24 14:25
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

Pozostało 580 znaków

2011-08-24 15:16
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())
edytowany 1x, ostatnio: vpiotr, 2011-08-24 15:17

Pozostało 580 znaków

2011-08-24 15:23
0

A nie łatwiej:

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

Pozostało 580 znaków

2011-08-24 15:28
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.

Pozostało 580 znaków

2011-08-24 15:29
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


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
edytowany 2x, ostatnio: MasterBLB, 2011-08-24 15:46

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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