This forum contains many examples of such situation, but in my case static variables are defined correctly, however I still get that error. So this issue is not duplicate of previous and above link does not answer the question. Suggested 21 answers post does not have solution Simon gave me here, please unmark this as "duplicate".
Seems I've declared all correctly, check this:
.h file:
class ValueSetsModelsContainer : public QObject
{
Q_OBJECT
public:
static void DLLEXPORT loadAllergiesValueSets(MPTDatabase *db);
static void DLLEXPORT loadProceduresValueSets(MPTDatabase *db);
// Models access functions
static QStandardItemModel *drugsModel();
static QStandardItemModel *substanceModel();
static QStandardItemModel *reactionsModel();
private:
static QStandardItemModel *myDrugsModel, *mySubstanceModel, *myReactionsModel;
};
.cpp:
QStandardItemModel *ValueSetsModelsContainer::myDrugsModel = 0;
QStandardItemModel *ValueSetsModelsContainer::mySubstanceModel = 0;
QStandardItemModel *ValueSetsModelsContainer::myReactionsModel = 0;
QStandardItemModel *ValueSetsModelsContainer::drugsModel()
{
return ValueSetsModelsContainer::myDrugsModel;
}
QStandardItemModel *ValueSetsModelsContainer::substanceModel()
{
return ValueSetsModelsContainer::mySubstanceModel;
}
QStandardItemModel *ValueSetsModelsContainer::reactionsModel()
{
return ValueSetsModelsContainer::myReactionsModel;
}
So static variables are defined in cpp, however I still get linking error in another module which calls ValueSetsModelsContainer methods:
allergiesdialog.obj:-1: error: LNK2001: unresolved external symbol
"private: static class QStandardItemModel *
ValueSetsModelsContainer::myDrugsModel"
(?myDrugsModel#ValueSetsModelsContainer##0PAVQStandardItemModel##A)
allergiesdialog.obj:-1: error: LNK2001: unresolved external symbol "private: static class QStandardItemModel *
ValueSetsModelsContainer::mySubstanceModel"
(?mySubstanceModel#ValueSetsModelsContainer##0PAVQStandardItemModel##A)
allergiesdialog.obj:-1: error: LNK2001: unresolved external symbol "private: static class QStandardItemModel *
ValueSetsModelsContainer::myReactionsModel"
(?myReactionsModel#ValueSetsModelsContainer##0PAVQStandardItemModel##A)
Where the problem could be?
From your link commands it turned out that you are linking together objects into a DLL and then in a second step link the DLL with your final binary. This might be caused by a subdirs template in your project settings.
Whenever you want to have a method of a DLL available from outside, you need to make it available via __declspec( dllexport ). I guess this is done in your custom precompiler constant DLLEXPORT.
Now try this in your .h file:
static DLLEXPORT QStandardItemModel *drugsModel();
static DLLEXPORT QStandardItemModel *substanceModel();
static DLLEXPORT QStandardItemModel *reactionsModel();
to make those methods available from outside the DLL.
By the way: I don't think it makes sense here to have an intermediate dynamic library (DLL) if you are just linking stuff from your own project and don't need to make it available to someone else. Consider using a static library instead by setting TEMPLATE = lib and CONFIG += staticlib in the .pro file where ValueSetsModelsContainer is in. But this is another topic and another question.
Related
I am working with Qt 5.7 (C++).
Inside the cpp file of one class I am using an anonymous namespace to create a class (some utility) that I will use only in that file.
However, I got Linking errors if the utility-class is derived from a Qt class. I think that the problem is at the Q_OBJECT macro, if I don't add it I don't get the errors. But in any Qt derived class is imperative/recommended to have the Q_OBJECT macro.
How can I avoid this isue?
Is there any other approach to have a utility-class with file-scope?
Simple example to show errors: the class CMyClass uses a utility class (named CUtility) that derives from QWidget.
Thank you.
CMyClass.h
class CMyClass
{
public:
CMyClass();
void someMethod();
};
CMyClass.cpp
#include <QtWidgets>
#include "CMyClass.h"
namespace
{
class CUtility : public QWidget
{
Q_OBJECT
public:
CUtility(QWidget *p_parent = 0) : QWidget(p_parent){qDebug() << "CUtility constructor";}
void utilityMethod() {qDebug() << "This is CUtility::utilityMethod()";}
};
}
CMyClass::CMyClass()
{
qDebug() << "CMyClass constructor.";
}
void CMyClass::someMethod()
{
qDebug() << "This is CMyClass::someMethod().";
CUtility p_myUtil;
p_myUtil.utilityMethod();
}
The errors are:
LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __cdecl `anonymous namespace'::CUtility::metaObject(void)const " (?metaObject#CUtility#?A0x27a8253c##UEBAPEBUQMetaObject##XZ)
LNK2001: unresolved external symbol "public: virtual void * __cdecl `anonymous namespace'::CUtility::qt_metacast(char const *)" (?qt_metacast#CUtility#?A0x27a8253c##UEAAPEAXPEBD#Z) sin resolver
LNK2001: unresolved external symbol "public: virtual int __cdecl `anonymous namespace'::CUtility::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall#CUtility#?A0x27a8253c##UEAAHW4Call#QMetaObject##HPEAPEAX#Z) sin resolver
This has nothing to do with anonymous namespaces at all. They are a non sequitur, in fact.
Recall that moc generates the implementations of a few methods, including signals, and some static data. For this to work, the class declaration must be visible to moc output. It is visible at the end of the .cpp file.
Thus, to have a Q_OBJECT class inside a foo.cpp file, you must #include "foo.moc" at the end of that file. Then just re-build if using cmake, or, for qmake, re-run qmake first and then build the project. That's all.
In the complete example below, the Utility class can be in the anonymous namespace, but doesn't have to be. The anonymous namespace isn't "really" a namespace: it has a special meaning that limits the scope of the contained identifiers to the translation unit. It's like static, except it can be also applied to types, not only functions and variables.
// main.cpp
#include <QObject>
namespace {
class Utility : public QObject {
Q_OBJECT
public:
Utility(QObject *parent = {});
};
}
Utility::Utility(QObject *parent) : QObject(parent) {}
int main() {
Utility utility;
}
#include "main.moc"
It doesn't work with the Q_OBJECT macro because the macro add members to your class, members which are defined in the C++ code generated by the moc (generally in moc_CMyClass.cpp making it incompatible with a file-scope).
One possible solution is to skip the Q_OBJECT macro, it is not mandatory and you may not need it. The drawback is that you will lose introspection information about your class and cannot declare signals and slots.
The other solution is, as suggested by #KubaOber, to include the generated cpp file at the end of your own copy file. In this case qmake will detect it and will not compile the moc
cpp file on its own.
I am new to c++. I started now playing with classes and I am having a noob problem with statics.
class Test
{
public:
Test(){};
~Test(){};
static void test();
static Helper* helper;
};
void Test::test()
{
Object obj = Test::helper->getObject();
//...
}
When I try to compile it gives the error:
main.obj : error LNK2001: unresolved external symbol "public: static class Helper* Test::helper" (?helper#Test##2PAVHelper##A)
What is wrong with my code?
The first answer is correct. The reason behind this is that you need to allocate memory for static objects outside the class definition. If you define the the class in a header file, and include it in several cpp files, the compiler doesn't know where and how you want to create the object that 'helper' points to.
you need to define Test::helper. Write something like this outside the class:
Helper* Test::helper = new Helper;
Consider the following source of From.dll library defining the From class:
Header:
// From.h
#include <afxwin.h>
#include <afxext.h>
class AFX_EXT_CLASS From
{
public:
static const char staticMember[666];
};
Implementation:
// From.cpp
#include "From.h"
const char From::staticMember[] = "Total Crap";
This library static member staticMember must be used from the following To class, which must also give rise to a DLL (To.dll):
Header:
// To.h
#include <afxwin.h>
#include <afxext.h>
class AFX_EXT_CLASS To
{
public:
static const char* retExtStatic();
};
Implementation:
// To.cpp
#include "To.h"
#include "From.h"
const char* To::retExtStatic()
{
return From::staticMember;
}
But I keep getting this LNK2001: unresolved external symbol "public: static char const * const From::staticMember" (?staticMember#From##2QBDB) when linking To.dll, no matter if it's directly on Visual Studio or if it's a cmake generated nmake:
Linking CXX shared library To.dll
Creating library To.lib and object To.exp
To.cpp.obj : error LNK2001: unresolved external symbol "public: static char const * const From::staticMember" (?staticMember#From##2QBDB)
To.dll : fatal error LNK1120: 1 unresolved externals
The first DLL is compiled and linked allright. The following are the relevant parts of my CMakeLists.txt:
add_definitions (-D_AFXDLL -D_AFXEXT -DPSAPI_VERSION=1)
set (CMAKE_MFC_FLAG 2) # Use MFC in a shared DLL
# FROM
file (GLOB FROM ${CMAKE_CURRENT_SOURCE_DIR}/From.cpp)
add_library (From SHARED ${FROM})
target_link_libraries (From)
# TO
file (GLOB TO ${CMAKE_CURRENT_SOURCE_DIR}/To.cpp)
add_library (To SHARED ${TO})
target_link_libraries (To From)
What am I doing wrong to export this static data member?
As #Niall and #Igor Tnadetnik pointed out on comments on the question, when a DLL needs another DLL, it's not safe to include the header file of the DLL to be used if therein the class is declared with AFX_EXT_CLASS. In this case, as the client code is also a DLL, AFX_EXT_CLASS would be defined as __declspec(dllexport) and not as __declspec(dllimport) as it should.
Here is my simple setup: (i've hidden lots of unneeded information)
//AutoFocusTest.h
#include "camAVTEx.h"
class CAutoFocusTestApp : public CWinApp
{
protected:
camera_t* mCamera;
public:
virtual BOOL InitInstance();
};
//camAVTEx.h
class camera_avtcam_ex_t : public camera_t
{
public:
camera_avtcam_ex_t();
virtual ~camera_avtcam_ex_t();
//member variables
//member function declarations
}
//camAVTEx.cpp
#include "camAVTEx.h"
camera_avtcam_ex_t::camera_avtcam_ex_t()
{
//stuff
}
camera_avtcam_ex_t::~camera_avtcam_ex_t()
{
//stuff
}
//the rest are defined here in my program
//AutoFocusTest.cpp
#include AutoFocusTest.h
BOOL CAutoFocusTestApp::InitInstance()
{
mCamera = new camera_avtcam_ex_t();
}
This setup produces the error:
3>AutoFocusTest.obj : error LNK2001: unresolved external symbol
"public: __cdecl camera_avtcam_ex_t::camera_avtcam_ex_t(void)"
(??0camera_avtcam_ex_t##QEAA#XZ)
From everything I've read on this relatively common problem, I have not linked something causing my camera_avtcam_ex_t function definitions to not be found. However, I can't figure out what I could have missed. I have added all of the include directories and library directories, as well as added the library files to the additional dependencies section.
Can anyone spot anything that I might be missing?
Assuming you have defined the constructor for your camera_avtcam_ex_t, it's declared as private, you can't instantiate it.
I have a Qt application with multiple classes that use signals and slots and it compiles just fine. However, when I make a custom class inside the main CPP (main.cpp) file, I get a linker error.
Here is the code I use:
class Counter : public QObject
{
Q_OBJECT
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
public slots:
void setValue(int value)
{
if(value!=m_value)
{
m_value = value;
qDebug() << "Value " << value;
emit valueChanged(value);
}
}
signals:
void valueChanged(int newValue);
private:
int m_value;
};
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int)));
a.setValue(12); // a.value() == 12, b.value() == 12
b.setValue(48); // a.value() == 12, b.value() == 48
QTimer::singleShot(0, &app, SLOT(quit()));
return app.exec();
}
Here are the errors:
Error 4 error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall Counter::metaObject(void)const " (?metaObject#Counter##UBEPBUQMetaObject##XZ)
Error 5 error LNK2001: unresolved external symbol "public: virtual void * __thiscall Counter::qt_metacast(char const *)" (?qt_metacast#Counter##UAEPAXPBD#Z)
Error 6 error LNK2001: unresolved external symbol "public: virtual int __thiscall Counter::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall#Counter##UAEHW4Call#QMetaObject##HPAPAX#Z)
Error 7 error LNK2019: unresolved external symbol "protected: void __thiscall Counter::valueChanged(int)" (?valueChanged#Counter##IAEXH#Z) referenced in function "public: void __thiscall Counter::setValue(int)" (?setValue#Counter##QAEXH#Z)
This linker error does not occur when I place the counter in a separate header file. What's the reason for this behavior?
I'm assuming you're working with qmake.
The moc is made to run on header files automatically by default, because that's where classes are declared in general. Notice that this rule is defined in the makefile, you can manually run moc on a source file.
You have to inform qmake that the file contains a class. To do this, put #include "filename.moc" after the declaration of Counter. You can see more details here (QtCentre) or here (doc).
If you're working with another tool than qmake, say CMake, you have to specify a rule to force the moc to parse the .cpp files (the simplest is to process them all). For files that do not contain a Qt object class, moc will generate an empty file.
However, even if this class is made to be 'private', I advise you to declare it in a header (for example counter_private.h). For example, Qt source is using this trick.
It looks like you have only one code file. If you use the default way to create a Qt project build (qmake && make or QtCreator), the MOC only scans *.h files. If you have all your code in one main.cpp the MOC will not create any code, but that's needed for Signal/Slots to work.
The simplest way to make this specific example working would be adding a line "#include "main.moc"" at the end of your main.cpp. This dependency will be detected by qmake and the needed Makefile targets will be created.
The cutest way would be the clean one: One class - One header and one implementation file.
They moc/uic custom build commands are done on the header file, so it compiles when put in a seperate header/source file and not when put in the same source file