0
votes

I have a problem with linking my project. I'm trying to create shared library which could be used between three different projects. This library will be used for parsing XML files and general handling with objects from these XML files.

Here is minimal example which is affected. Library project consist of these files

============= Library.cpp =============
#include "library.h"

Library::Library(QString name){
this->name = name;
}

============= Library.h =============
#ifndef LIBRARY_H
#define LIBRARY_H

 #include <QString>

 class Library
 {

 public:
   Library(QString name);

private:
   static QString name;
};
#endif // LIBRARY_H

============= Library.pro =============
QT       -= gui
TARGET = Library
TEMPLATE = lib
CONFIG += staticlib
SOURCES += library.cpp
HEADERS += library.h
unix {
   target.path = /usr/lib
   INSTALLS += target
}

Main application is made by these files.

============= main.c =============
#include <QCoreApplication>
#include "library.h"

int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   Library lib("MyLib");

   return a.exec();
}

============= Application.pro =============
QT += core
QT -= gui

TARGET = Application
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
SRCDIR = $$IN_PWD/../Library
INCLUDEPATH += $$SRCDIR
SRCDIR = $$IN_PWD/../Library
INCLUDEPATH += $$SRCDIR

LIBDIR = $$IN_PWD/../build-Library-Desktop_Qt_5_5_1_GCC_64bit-Ladění/libLibrary.a
LIBS += $$LIBDIR

Here is the output of linker

g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIC -DQT_CORE_LIB -I../Application -I. -I../Library -I../Library -I../../../Qt/5.5/gcc_64/include -I../../../Qt/5.5/gcc_64/include/QtCore -I. -I../../../Qt/5.5/gcc_64/mkspecs/linux-g++ -o main.o ../Application/main.cpp

g++ -Wl,-rpath,/home/mint/Qt/5.5/gcc_64 -Wl,-rpath,/home/mint/Qt/5.5/gcc_64/lib -o Application main.o   /home/mint/Development/test/Application/../build-Library-Desktop_Qt_5_5_1_GCC_64bit-Ladění/libLibrary.a -L/home/mint/Qt/5.5/gcc_64/lib -lQt5Core -lpthread 

/home/mint/Development/test/Application/../build-Library-Desktop_Qt_5_5_1_GCC_64bit-Ladění/libLibrary.a(library.o): In function `Library::Library(QString)':

Makefile:214: recipe for target 'Application' failed

/home/mint/Development/test/build-Library-Desktop_Qt_5_5_1_GCC_64bit-Ladění/../Library/library.cpp:6: undefined reference to `Library::name'
collect2: error: ld returned 1 exit status

When I change static QString name in Library.h to non static variable, then everything is ok. It could be linked then. I think, that project files are setup correctly, but what am I missing ?

2

2 Answers

1
votes

In C++, static member variables are essentially global exported "class variables" (so very different from other static variables, in a sense even opposite, you make file scope variables static to avoid them being exported globals).

And in that .h file, you only have variable declaration: you declare that this kind of variable exists, somewhere.

However, to actually make it exist for real, you have to define it. Therefore you need to add this to one .cpp file:

QString Library::name = QStringLiteral("initial value");

Additionally, it is class variable, so you (probably) shouldn't change it every time an instance is created, so your consturctor would be just:

Library::Library() {
}

If you want to initialize it from somewhere else (quite probably main(), to replace the code in your constructor, simply assign to it:

Library::name = whatever;

However, if you actually want to have it as instance variable (each instance/object of the class has its own copy), then just remove static from the definition in the .h file.

Also, with global variables (including static class variables), you have to be careful about initialization order. They're also global variables, with all the trouble that can bring. So, if you don't really need them, don't use them.

0
votes

in C++, static member should be defined and initialized outside the class declaration.

============= Library.h =============
#ifndef LIBRARY_H
#define LIBRARY_H

#include <QString>

class Library
{
public:
    Library(QString name);

private:
    static QString name;// declare
};
#endif // LIBRARY_H    

============= Library.cpp =============
#include "library.h"

//add this line if name is static member of Library
QString Library::name;// define and initialize

//you can also initialize it to other value like:
//QString Library::name = "banana!";

Library::Library(QString name){
    this->name = name;
}