Unresolved external symbol on static class members - c++

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.]

Related

Why the singleton initialization failed (link error) [duplicate]

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.]

How to access and initialize std::list from a class

My question could be silly but I am having following problem.
Following piece of code works just fine. I have list that is global or local and can instantiate and push values correctly.
class THistory
{
public:
UInt32 index;
UInt32 navToID;
};
//Works Fine
class ML{
public:
static THistory *hist2;
};
main.cpp;
ML::hist2 = new THistory[HISTORY_BUFFER_SIZE];//global
std::list<THistory> histList;//global
histList.push_back(ML::hist2[0]);//inside main()
Problem starts when I move the list inside a class.
//Problem
class ML{
public:
static THistory *hist2;
static std::list<THistory> histList; //replace global list and put it inside ML class as static
}
main.cpp;
ML::hist2 = new THistory[HISTORY_BUFFER_SIZE];//global as before
////// Where to initialize the list?
ML::histList.push_back(CoreML::hist2[0]); //inside main()
//LINK Error Undefined symbol
error LNK2001: unresolved external symbol "public: static class std::list > CoreML::histList" (?histList#CoreML##2V?$list#VTHistory##V?$allocator#VTHistory###std###std##A)
I dont know how to initialize the list. any pointers will be helpful.
In C++, if you declare a static member variable inside of a class, you need to put a definition of that variable somewhere. The linker error you're getting is because you've declared the variable, but you haven't defined it.
In one of the C++ source files in your program, add this line:
std::list<THistory> CoreML::histList; // Define the variable.
Within a class definition static data members are only declared. You have to define them outside the class definition. For example
class ML{
public:
static THistory *hist2;
static std::list<THistory> histList; //replace global list and put it inside ML class as static
};
^^^
// before the function main
std::list<THistory> ML::histList;

Unresolved external symbol C++

I ahve a problem with a code below:
ProgrammSettings.h
#pragma once
static class ProgrammSettings
{
public:
static int fd;
};
Settings.cpp
#include "ProgrammSettings.h"
static bool LoadSettings()
{
ProgrammSettings::fd = 2; // here error Unresolved symbol!!
return true;
}
What i'm doing wrong?
Thanks!
Unlike instance variables that require only a declaration, static member variabs of the class must also be defined.
Currently, your code contains only a declaration. Add a definition of your static fd variable to a cpp file to fix the error:
int ProgrammSettings::fd;
You need to add the following line to the start of your cpp file
int ProgrammSettings::fd;
Static data members declarations in the class declaration are not definition of them
You have forgot to add the definition to match your declaration of fd.You must explicitly define your class's static data members.

Class declaration in a header file and static variables

Noob question, but would like to understand the following:
Imagine I have a multifile project. I'm specifying a class in a header file to be shared among all the files in the project, and I write this : static int test = 0; and in the next line this: static const int MAX = 4;
The first one would be an error trying to compile because of the one definition rule. But the second one will compile without errors. Why?
From what I understand, both have the same properties: whole execution storage duration, class scope and no linkage.
Any help?
EDIT: testing an external constant declaration in a header: extern const int MAX = 4; to force external linkage produced the expected error. So I don't understand why with the variable it gives me the error and with the constant it doesn't.
Try
static const int test = 0;
I've sometimes noticed compiler errors with the immediate initialization of static const variables in the header file. You can always use the declaration in the header
class MyClass
{
// ...
static const int test;
// ...
}
and initialize it in the corresponding .cpp file
const int MyClass::test = 0;
This should work properly with any other types than int as well.
Integer constants in C++ don't actually occupy any space in the object and don't act like variables in general. Think about them more like numbers that are given names in this particular context.

Linker errors with private members of class in header file

I'm trying to build a project in Visual Studio 2008. I'm getting a bunch of linker errors that are really bothering me. My application is a Win32 console application using only native ANSI C++.
They are all linker errors of the same pattern.
Linker errors are related to every single private static data member of classes I have defined in my own header files.
I'm guessing this is probably a simple fact of c++ I'm not already aware of?
Example:
I refer to the members of SingleDelay within function definitions of SingleDelay's member classes in a file Delays.cpp.
ie:
SingleDelay::tick(void *output, void *input, int nbufferFrames)<br>{
//.. code here<br>
x = dry * castInput + wet * castInput;<br>
}
Error 38 error LNK2001: unresolved external symbol "private: static double SingleDelay::dry" (?dry#SingleDelay##0NA) Delays.obj testall
Definition of SingleDelay in Delays.h:
class SingleDelay{
private:
static double dry; //% of dry signal<br>
static double wet; //% of wet signal<br>
static unsigned int delay; //Delay in milliseconds<br>
static int delayCell; //Index in the delayBuffer of the delay to add<br>
static double *delayBuffer; //Delay buffer is 1 second long at sample rate SAMPLE_RATE<br>
static unsigned int bufferCell; //Pointer to the current delay buffer cell<br>
public:
//Tick function
static void tick(void *output, void *input,int nBufferFrames);
//Set and Get functions
static void setSingleDelay(double tDry, double tWet, unsigned int tDelay);
static void setSingleDelay(void);
static void setDry(double tDry);
static void setWet(double tWet);
static void setDelay(unsigned int tDelay);
static double getDry(){ return dry;}
static double getWet(){ return wet;}
static unsigned int getDelay(){ return delay;}
static void initializeDelayBuffer(){
destroyDelayBuffer();
delayBuffer = new double[bufferLength];
}
static void destroyDelayBuffer(){
delete[ ] delayBuffer;
}
};
They are all linker errors of the same pattern. Linker errors are related to every single private static data member of classes I have defined in my own header files.
All static data members must have a definition in a .cpp file somewhere.
Error 38 error LNK2001: unresolved external symbol "private: static double SingleDelay::dry" (?dry#SingleDelay##0NA) Delays.obj testall
The linker is telling you that there is no defined storage for that variable. This line must appear somewhere in exactly one .cpp file:
double SingleDelay::dry = 0.0;
Maybe you haven't added the library and include paths of the library you use to the project definitions?
C++ error are always fun to look at. Or not. In any case, do you initialize your static variables anywhere? You need to do this in a .cpp file somewhere. And remember to use static variables with care. They are actually global variables in disguise, and can make future changes, such as multi-threading, more difficult.
Maybe error consists in your static fields visibility scope, because they are private.
Try write code that use your privete static field in class definition, not beyond your class.
Write this method just in your class definition:
class SingleDelay{
...
int tick(void *output, void *input, int nbufferFrames)
{ //.. code here
x = dry * castInput + wet * castInput;
}
...
}
You need to add the .cpp and .h files to .vcproj file.