I know that this subject has already been discussed on this site, I tested the solutions but it doesn't work, I always have the same mistake. Please help me :')
Player.cpp
#include "Player.hpp"
namespace Player
{
const char *name = "Jason";
}
Card.cpp
#include "Player.hpp"
namespace Player
{
const char *name = "Jason";
}
Player.hpp
namespace Player
{
extern const char *name;
}
You can have at most one definition of each unique fully-qualified symbol in your program. The linker error you are receiving is occurring because you provide a definition for the symbol Player::name in both Player.cpp and Card.cpp.
You are free to reuse variable names; but the symbol must still be unique to avoid these issues. For your particular problem, this may be solved through one of the following:
Defining the symbol in a different namespace
For example, you could change Card.cpp to be:
// Symbol is Card::name -- which is different from Player::card
namespace Card {
const char* name = ...;
} // namespace
Defining the symbol as a static member of a struct/class
This could be something like:
// Symbol is Player::Card::name -- which is different from Player::card
namespace Player {
struct Card {
static const char* name = ...;
};
}
Marking the symbol with internal linkage
This could be done using an unnamed namespace (C++11 and above), or static (older C++):
// Symbol is Player::<some unique name>::name
namespace Player {
namespace {
const char* name = ...;
}
// or 'static const char* name = ...;'
}
note: This method, unlike the others, cannot be used across different source files. The symbol is "internalized", which means it is unique to the one compilation unit (source file).
Related
Let's assume there are a number of variables defined in namespace library::symbols that are supposed to initialize on startup, like this:
namespace library {
class Symbol; // details not relevant here
namespace symbols {
inline const Symbol S1 = Symbol("S1");
inline const Symbol S2 = Symbol("S2");
}
}
Now, I need to add more of those from other places, referencing back into the symbols namespace (pseudo code):
namespace app {
namespace ::library::symbols {
inline const Symbol S3 = Symbol("S3");
inline const Symbol S4 = Symbol("S4");
}
}
The rationale behind this is to have an extensible set of global constants that can be compared, parsed and printed at runtime (example names S1...S4 are arbitrary here).
The example doesn't compile. I tried a bunch of ideas, but can't seem to find any solution yet. What am I missing? Is there a way to reopen and extend the library::symbols namespace? Is there an alternative to achieve this, e.g. via template specialization?
EDIT:
Reframed the question and second code snippet to be more precise. The issue I have is how to extend a namespace outside the current namespace. In the example, I would need to extend symbols while inside namespace app.
So the question is if there's a way to alias back into a higher-level namespace without this causing the declaration of a new one.
Is there a way to reopen and extend the library::symbols namespace?
Yes, you said it. Just reopen the library::symbols namespace and put more data in it. For example:
namespace library
{
class Symbol;
namespace symbols
{
inline const Symbol S1 = Symbol("S1");
inline const Symbol S2 = Symbol("S2");
}
}
// Maybe in another file
namespace library
{
class Symbol;
namespace symbols
{
inline const Symbol S3 = Symbol("S1");
inline const Symbol S4 = Symbol("S2");
}
}
namespace app
{
using namespace library;
Symbol dummy()
{
// Here use a namespace variable
return symbols::S3;
}
}
You just have to remember to include the correct header if you reopen the namespace in another file.
Just do what you did in the declaration of first set of variables:
namespace library {
namespace symbols {
inline const Symbol S3 = Symbol("S3");
inline const Symbol S4 = Symbol("S4");
}
}
Edit:
In the example, I would need to extend symbols while inside namespace app.
This isn't possible. The solution is to not try to do that. Close the namespace app, then follow the example I gave above. You can re-open app afterwards if necessary.
I am trying to register a file including only a namespace with qmlRegisterUncreatableMetaObject for use in QML
The Namespace is in my constants.h file which looks as follows:
#ifndef K_CONSTANTS_H
#define K_CONSTANTS_H
#include <QString>
#include <QObject>
static const QString K_Red = "#d20019";
static const QString K_DarkRed = "#a20000";
static const QString K_Green = "#1da019";
static const QString K_DarkGray = "#FF4b4b4b";
static const unsigned int EXIT_CODE_REBOOT = 1234567890;
namespace Strings {
Q_NAMESPACE
static const char* REPAIR = QT_TR_NOOP("Repair");
static const char* MAINTENANCE = QT_TR_NOOP("Maintenance");
static const char* DISTURBANCE = QT_TR_NOOP("Disturbance");
static const char* MEAL_BREAK = QT_TR_NOOP("Meal Break");
}
#endif // K_CONSTANTS_H
I am trying to register with in the constructor of K_Administration.cpp which is called before the app.exec() is called.
qmlRegisterUncreatableMetaObject(Strings::staticMetaObject, "MyConstants", 1, 0, "Strings", "Not Instantiable!" );
this always results in
k_administration.obj:-1: Error: LNK2001: unresolved external symbol
"struct QMetaObject const Strings::staticMetaObject"
(?staticMetaObject#Strings##3UQMetaObject##B)
I can access the Namespace from everywhere in my project. It is also possible to call just Strings::staticMetaObject. but it seems to fail as soon as Strings::staticMetaObject is assigned to a value.
Maybe it is important to know that K_Administration.cpp and K_Constants.h are in 2 different subprojects of my project
Since K_Administration and K_Constants are in two different projects it is necassary to add an export delcaration. This can be in an other file and inlcuded or in the same file.
#if defined(CONSTANTS_LIBRARY)
# define CONSTANTS_EXPORT Q_DECL_EXPORT
#else
# define CONSTANTS_EXPORT Q_DECL_IMPORT
#endif
to export the namespace i it its necassary to add it to the namespace
CONSTANTS_EXPORT Q_NAMESPACE
NOTE: I made the mistake that i wanted to add the CONSTANTS_EXPORT declaration to the namespace definition line. something like namespace CONSTANTS_EXPORT Strings {} because there is a similar syntax for classes. but in a namespace it a declaration for Q_NAMESPACE. I think it is possible to use Q_NAMESPACE_EXPORT and leave the export declaration for Qt 5.14 and above.
In a big project, I have a .h file which defines a lot of constants within a namespace. Introducing const char* constants results in linker errors complaining of multiple definitions.
ex.h
#include <string>
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char* NAME2 = "fred"; // <-- ERROR: multiple definition of `Dv::NAME2'
}
exA.cpp
#include "ex.h"
void aFunction() { printf("this is aFunction\n"); }
exB.cpp
#include "ex.h"
void aFunction(void);
int main(int argc, char **argv)
{
aFunction();
return 0;
}
Compile and Link
g++ -c exA.cpp
g++ -c exB.cpp
g++ exA.o exB.o -o ex
exB.o:(.data+0x0): multiple definition of `Dv::NAME2'
exA.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
The linker error happens if NAME2 is included in the .h file. Why?
If MAX is also a POD (like char[]?), why does the linker not complain of multiple int MAX definitions? (or multiple std::string NAME definitions for that matter?)
I don't understand what's special about char[] in this situation.
Thanks
According to the C++ Standard (3.5 Program and linkage)
3 A name having namespace scope (3.3.6) has internal linkage if it is
the name of
— a non-volatile variable that is explicitly declared const or constexpr and neither explicitly declared extern nor previously
declared to have external linkage; or
and
4 An unnamed namespace or a namespace declared directly or indirectly
within an unnamed namespace has internal linkage. All other
namespaces have external linkage. A name having namespace scope that
has not been given internal linkage above has the same linkage as the
enclosing namespace if it is the name of — a variable; or
In this namespace definition
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char* NAME2 = "fred"; // <-- ERROR: multiple definition of `Dv::NAME2'
}
(the only) variable NAME2 is not a constant and hence has external linkage.
You could make it as having internal linkage defining it for example with keyword static. For example
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
static const char* NAME2 = "fred";
}
Or could define it as a constant
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char * const NAME2 = "fred";
}
Could someone please advise?
If const in C++ defaults to internal linkage, why do I get multiple definition errors in the code below?
First, the file dem.h:
#ifndef _DEM_H_
#define _DEM_H_
class Dem {
public:
static const int i;
};
const int Dem::i = 10;
#endif
Them imp1.cpp:
#include "dem.h"
#include <iostream>
using namespace std;
extern int foo();
int main() {
cout << foo() << endl;
}
and imp2.cpp:
#include "dem.h"
int foo() {
return Dem::i ;
}
I compile with the following command and results:
$ g++ imp1.cpp imp2.cpp
/tmp/ccmGt0OY.o:imp2.cpp:(.rdata+0x0): multiple definition of `Dem::i'
/tmp/cc5sN7dz.o:imp1.cpp:(.rdata+0x0): first defined here
collect2: ld returned 1 exit status
From C++11 [basic.link], paragraph 5:
In addition, a member function, static data member, a named class or enumeration of class scope, or an unnamed class or enumeration defined in a class-scope typedef declaration such that the class or enumeration has the typedef name for linkage purposes (7.1.3), has external linkage if the name of the class has external linkage.
Because your class has external linkage, so does your static data member.
Its static to the compilation unit. You are compiling in two steps - first impl1.cpp and then impl2.cpp - and in each unit the compiler instantiates the static data member. When the linker then tries to link the two associated object files together, it sees two different definitions for the same symbol , and so you get a multiple definition error.
Very simply put:
I have a class that consists mostly of static public members, so I can group similar functions together that still have to be called from other classes/functions.
Anyway, I have defined two static unsigned char variables in my class public scope, when I try to modify these values in the same class' constructor, I am getting an "unresolved external symbol" error at compilation.
class test
{
public:
static unsigned char X;
static unsigned char Y;
...
test();
};
test::test()
{
X = 1;
Y = 2;
}
I'm new to C++ so go easy on me. Why can't I do this?
If you are using C++ 17 you can just use the inline specifier (see https://stackoverflow.com/a/11711082/55721)
If using older versions of the C++ standard, you must add the definitions to match your declarations of X and Y
unsigned char test::X;
unsigned char test::Y;
somewhere. You might want to also initialize a static member
unsigned char test::X = 4;
and again, you do that in the definition (usually in a CXX file) not in the declaration (which is often in a .H file)
Static data members declarations in the class declaration are not definition of them.
To define them you should do this in the .CPP file to avoid duplicated symbols.
The only data you can declare and define is integral static constants.
(Values of enums can be used as constant values as well)
You might want to rewrite your code as:
class test {
public:
const static unsigned char X = 1;
const static unsigned char Y = 2;
...
test();
};
test::test() {
}
If you want to have ability to modify you static variables (in other words when it is inappropriate to declare them as const), you can separate you code between .H and .CPP in the following way:
.H :
class test {
public:
static unsigned char X;
static unsigned char Y;
...
test();
};
.CPP :
unsigned char test::X = 1;
unsigned char test::Y = 2;
test::test()
{
// constructor is empty.
// We don't initialize static data member here,
// because static data initialization will happen on every constructor call.
}
in my case, I declared one static variable in .h file, like
//myClass.h
class myClass
{
static int m_nMyVar;
static void myFunc();
}
and in myClass.cpp, I tried to use this m_nMyVar. It got LINK error like:
error LNK2001: unresolved external symbol "public: static class...
The link error related cpp file looks like:
//myClass.cpp
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}
So I add below code on the top of myClass.cpp
//myClass.cpp
int myClass::m_nMyVar; //it seems redefine m_nMyVar, but it works well
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}
then LNK2001 is gone.
Since this is the first SO thread that seemed to come up for me when searching for "unresolved externals with static const members" in general, I'll leave another hint to solve one problem with unresolved externals here:
For me, the thing that I forgot was to mark my class definition __declspec(dllexport), and when called from another class (outside that class's dll's boundaries), I of course got the my unresolved external error.
Still, easy to forget when you're changing an internal helper class to a one accessible from elsewhere, so if you're working in a dynamically linked project, you might as well check that, too.
When we declare a static variable in a class, it is shared by all the objects of that class. As static variables are initialized only once they are never initialized by a constructor. Instead, the static variable should be explicitly initialized outside the class only once using the scope resolution operator (::).
In the below example, static variable counter is a member of the class Demo. Note how it is initialized explicitly outside the class with the initial value = 0.
#include <iostream>
#include <string>
using namespace std;
class Demo{
int var;
static int counter;
public:
Demo(int var):var(var){
cout<<"Counter = "<<counter<<endl;
counter++;
}
};
int Demo::counter = 0; //static variable initialisation
int main()
{
Demo d(2), d1(10),d3(1);
}
Output:
Count = 0
Count = 1
Count = 2
In my case, I was using wrong linking.
It was managed c++ (cli) but with native exporting. I have added to linker -> input -> assembly link resource the dll of the library from which the function is exported. But native c++ linking requires .lib file to "see" implementations in cpp correctly, so for me helped to add the .lib file to linker -> input -> additional dependencies.
[Usually managed code does not use dll export and import, it uses references, but that was unique situation.]