Static Linking Problem in Qt with SQLite - c++

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()
{
....
}

Related

Header file is inaccessible

I'm using cocos2d-x to create my project but I'm getting this error:
Error (active) "CocosDenshion::SimpleAudioEngine::SimpleAudioEngine()"
(declared at line 256 of "c:\MyGame
\cocos2d\cocos\audio\include\SimpleAudioEngine.h") is
inaccessible MyGame c:\MyGame \Classes\MyGame .cpp
So I am including the SimpleAudioEngine.h file into my CPP file, to work with it. As you can see from the error, to use the SimpleAudioEngine, I need to use the CocosDenshion namespace first, but as soon as I am done typing:
CocosDenshion::SimpleAudioEngine()
Visual Studio shows this error to me, VS can show me the declaration, so that tells me that it knows where the header is and it can be read. So I don't know what is the issue for being inaccessible. What are some reason for header files to be inaccessible?
MyGame.cpp
#include "MyGame.h"
#include "SimpleAudioEngine.h"
#include "GlobalVariables.h"
USING_NS_CC;
Scene* MyGame::createScene()
{
auto scene = Scene::create();
auto layer = MyGame::create();
scene->addChild(layer);
return scene;
}
bool MyGame::init()
{
if (!Layer::init())
{
return false;
}
is_dragged = false;
const char* MUSIC_PATH = "Music/Main_Theme_loop.ogg";
initTouch();
initTiled();
tempSetupSprite();
debugDrawLine();
this->scheduleUpdate();
return true;
}
MyGame.h
#include "GameSprite.h"
#include "GameMap.h"
class MyGame : public cocos2d::Layer
{
private:
void update(float dt);
void initTouch();
void initTiled();
void tempSetupSprite();
void debugDrawLine();
public:
static cocos2d::Scene* createScene();
virtual bool init();
virtual bool onTouchBegan(cocos2d::Touch* _touch, cocos2d::Event* _event);
virtual void onTouchEnded(cocos2d::Touch* _touch, cocos2d::Event* _event);
virtual void onTouchMoved(cocos2d::Touch* _touch, cocos2d::Event* _event);
virtual void onTouchCancelled(cocos2d::Touch* _touch, cocos2d::Event* _event);
CREATE_FUNC(MyGame);
private:
bool is_dragged;
Vec2 first_touch;
Vec2 last_drag_touch;
GameSprite* sprite;
GameMap* map;
};
Looking at the documentation of cocos2d-x (http://www.cocos2d-x.org/reference/native-cpp/V3.5/de/d8f/class_cocos_denshion_1_1_simple_audio_engine.html). The constructor is protected. You have to use the following method to get the shared static simple audio engine instance:
getInstance()
Check "cocos2d.h" and you will find that "SimpleAudioEngine.h" is not included here. So you have to include it first when you try to use it.
Locating the header file by VS doesn't mean that the file is accessible in your cpp file. It is just a convenient function provided by VS to let the user easy to check the file.

How to resolve C2248: cannot access private member declared in Singleton class

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.

Using interface to export class from dll

IClass (My interface):
#ifndef _ICLASS_H
#define _ICLASS_H
#include <sstream>
namespace Test
{
class __declspec(dllexport) IClass
{
public:
virtual ~IClass() {}
virtual bool Init(const std::string &path) = 0;
};
}
#endif
Class.h
#ifndef _CLASS_H
#define _CLASS_H
#include "IClass.h"
#include <memory>
#include <sstream>
#include <stdio.h>
namespace Test
{
class Class: public IClass
{
public:
Class();
~Class();
bool Init(const std::string &path);
};
}
#endif
Class.cpp
#include "Class.h"
namespace Test
{
Class::Class()
{
}
bool Class::Init(const std::string &path)
{
try
{
// do stuff
return true;
}
catch(std::exception &exp)
{
return false;
}
}
}
main (in exe, dll linked implicitly)
#include "IClass.h"
using namespace Test;
int main(int argc, char* argv[])
{
std::shared_ptr<IClass> test = std::make_shared<Class>(); // error: unreferenced Class
test->Init(std::string("C:\\Temp"));
}
At the moment Class is not declared
-> if I include Class.h to main following error occurs: LNK2019: unresolved external symbol: add class __declspec(dllexport) Class : public IClass resolve this linker issue, but is it ok to do it this way?
-> I also can't do this: std::shared_ptr<IClass> test = std::make_shared<IClass>();
(because it's not allowed to create an object of abstract class)
How can I solve this issue and is this best practise?
If you want your EXE to allocate a new "Class" object, the EXE code has to know the Class type. If you want to keep the Class type unknown from the EXE, one solution may be to export from your DLL a factory function, which will construct a Class object and return it as an IClass pointer.
See How to implement the factory pattern in C++ correctly

Resolving circular dependency in the State Pattern with C++

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!).

LNK2019 && LNK1120 errors when splitting my code in multiple files

My code is stored in a main.cpp file which contains the void main() function, and a class MyClass which I now want to split to another file. IDE is Microsoft Visual Studio 2008 Professional.
myclass.h
#include <tchar.h>
class MyClass {
public:
static bool MyFunction (TCHAR* someStringArgument);
};
myclass.cpp
#include <tchar.h>
class MyClass {
private:
static bool someProperty;
static void doSomeOneTimeCode () {
if (!someProperty) {
/* do something */
someProperty = true;
}
}
public:
static bool MyFunction (TCHAR* someStringArgument) {
doSomeOneTimeCode();
/* do something */
return true;
}
};
bool MyClass::someProperty = false;
main.cpp
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include "myclass.h"
void main () {
if (MyClass::MyFunction(TEXT("myString"))) {
_tprintf(TEXT("Yay\n"));
}
}
However, when I try to run it, I get two linker errors.
LNK2019: unresolved external symbol ... (mentions MyClass::MyFunction)
LNK1120: 1 unresolved externals
What can I do to prevent these linker errors?
You declared two classes here. One of them is in myclass.h and the other is in myclass.cpp. Try the following instead:
myclass.h
#ifndef myclass_h_included
#define myclass_h_included
#include <tchar.h>
class MyClass {
private:
static bool someProperty;
static void doSomeOneTimeCode ();
public:
static bool MyFunction (TCHAR* someStringArgument);
};
#endif //!myclass_h_included
myclass.cpp
#include "myclass.h"
/*static*/ bool MyClass::someProperty = false;
void
MyClass::doSomeOneTimeCode() {
//...
}
bool
MyClass::MyFunction(TCHAR* someStringArgument) {
//...
}
Your main.cpp can stay the same. I would pay attention to UncleBens reply as well. One time initialization code should be hidden if at all possible.
Yo can't split a class definition in parts. It must be defined as a whole in one place. If you want to just have some methods of the class defined create a interface class that the MyClass class will later inherit. You should put the class' definition in a header file (myclass.h) and it's implementation in a cpp file (myclass.cpp). That way you can include the "myclass.h" in your main cpp file and use the class in your main function (which should be int main() or int main( int argc, char *argv[] )).
Strange that you didn't get a compiler error, as you are redefining MyClass.
Definitions (implementations) go into the cpp, and they are defined like this:
#include "myclass.h"
//helper functions, particularly if static, don't need to be in the class
//unnamed namespace means this stuff is available only for this source file
namespace
{
bool someProperty;
void doSomeOneTimeCode () {
if (!someProperty) {
/* do something */
someProperty = true;
}
}
}
bool MyClass::MyFunction (TCHAR* someStringArgument) {
doSomeOneTimeCode();
/* do something */
return true;
}