Compilation failed, c++ program with static variable as private member variable [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
undefined reference to static member variable
What is an undefined reference/unresolved external symbol error and how do I fix it?
#include<iostream>
using namespace std;
class abc {
private:
static int a ;
public:
abc(int x) {
a = x;
}
void showData() {
cout<<"A = "<<a<<endl;
}
};
int main() {
abc a1(4);
abc a2(5);
a1.showData();
a2.showData();
return 0;
}
When I try to compile this function on Ubuntu with GCC compiler. I get the following error.
/tmp/ccCKK2YN.o: In function `main':
static1.cpp:(.text+0xb): undefined reference to `Something::s_nValue'
static1.cpp:(.text+0x14): undefined reference to `Something::s_nValue'
collect2: ld returned 1 exit status
Compilation failed.
Where as the following code runs fine
#include<iostream>
using namespace std;
class Something
{
public:
static int s_nValue;
};
int Something::s_nValue = 1;
int main()
{
Something cFirst;
cFirst.s_nValue = 2;
Something cSecond;
std::cout << cSecond.s_nValue;
return 0;
}
Is this because Static member variables needs to initialized explicitly before accessing them via objects.Why so ?

static int s_nValue; doesn't allocate any storage to store the int, it just declares it.
You allocate somewhere in memory to store the variable with:
int Something::a=0;

The declaration of a static data member in the member list of a class is not a definition. You must define the static member outside of the class declaration, in namespace scope.
See this thread.
In short, the static member needs to be initialized somewhere in a .cpp file so that the compiler allocates space for it. The declaration would look like this:
int abc::a = 0;

That happens because since static members are shared between all instances of a class, they need to be declared in one single place.
If you define the static variable inside the class declaration then each include to that file would have a definition to that variable (which is against to the static meaning).
Because of that you have to define the static members in the .cpp.

Related

Declare static arrays in a struct right in C++

I tried to declare static array:
#include <iostream>
#include <string.h>
using namespace std;
struct tagData{
static string tags[];
};
int main(){
tagData::tags[3];
tagData::tags[0] = "default";
tagData::tags[1] = "player";
tagData::tags[2] = "enemy";
return 0;
}
But as the result an error occurred:
*Path*\cczPqyfY.o:main.cpp:(.text+0x1e): undefined reference to `tagData::tags[abi:cxx11]'
*Path*\cczPqyfY.o:main.cpp:(.text+0x32): undefined reference to `tagData::tags[abi:cxx11]'
*Path*\cczPqyfY.o:main.cpp:(.text+0x46): undefined reference to `tagData::tags[abi:cxx11]'
collect2.exe: error: ld returned 1 exit status
I was looking for some info about how to declare static arrays in structs, but couldn't.
Can anybody show me an example or help me in another way?
P.S.
I tried to compile this code with GCC version 8.1.0;
struct tagData{
static string tags[];
};
This static class member must be defined in global scope, and not as a local variable in a function like main:
string tagData::tags[3];
And now, once the formalities are taken care of, you can manually access its class members, in main or any other function:
int main(){
tagData::tags[0] = "default";
tagData::tags[1] = "player";
tagData::tags[2] = "enemy";
return 0;
}
However, if the goal is to initialize the array there's an even better way. Just initialize it as part of its definition:
string tagData::tags[3]={"default", "player", "enemy"};
Note: when defining static class member, you should always keep in mind the static initialization order fiasco.

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

Define main function in class [duplicate]

This question already has answers here:
in c++ main function is the entry point to program how i can change it to an other function?
(13 answers)
Closed 8 years ago.
I was wondering if its possible to define main() inside a class, something like:
struct runtime_entry_point
{
friend int main()
{
}
};
I have tested that and it doesn't work (Almost in GCC 4.8.2):
g++ -o dist/Release/GNU-Linux-x86/turbo build/Release/GNU-Linux-x86/main.o
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/crt1.o:
In function `_start': collect2: error: ld exited with status 1
This sounds to me like a no definition of main() error.
Later, I have written main in the classic way:
struct runtime_entry_point
{
friend int main()
{
}
};
int main(){}
Now the compilation fails because int main() was already defined inside the struct runtime_entry_point! Whats happening here?
Trivially it is not possible to write main as a part of a class/struct. The linker by default searches for a free main method and links against it, makes it the entry point. You may alter this behavior by at the linker level, in which case main must be a static method in class/struct. But this is linker implementation dependent, not-portable and dangerous.
However, in the second situation you mentioned is a result of violation of One Definition Rule. You are defining a name (main()) more than once in a single translation unit.
Аccording to the article on cppreference.com, the following construction:
struct runtime_entry_point
{
friend int main()
{
}
};
Defines a non-member function, and makes it a friend of this class at the same time. Such non-member function is always inline.
Linker couldn't find main() in object file (inline function), and you can't declare another main() in the same translation unit (as it already declared).
You can not define a function twice, it works when you change the definition into a declaration inside the class/struct:
#include <iostream>
struct runtime_entry_point
{
friend int main();
};
int main()
{
std::cout << "Hello, world!" << std::endl;
}
This works just fine with GCC.

static member inside class c++ undefined reference

Why this code is giving me an error that undefined reference to student::count. I am using static count and I know that static members are by default is 0 but dont know why giving me an error. Please explain me.
#include <iostream>
using namespace std;
class Student{
static int count;
string name;
public:
Student(){
count++;
cout<<"I am student"<<count<<endl;
}
int getCount() const
{
return count;
}
void setCount(int x){
count=x;
}
};
int main(){
Student stud[20];
return 0;
}
You have no definition of Student::count, violating the one definition rule. Put a definition in one, and only one, translation unit.
Note that if static int count; was a definition, static members would be almost impossible to use. You'd wind up with a definition each time you included the header file, making the one definition rule almost impossible to comply with.
Writing static int count; in your header means: Compiler, somewhere you will find a variable scoped to this class, it will be a int and will be nammed count.
Now, you need to actually instantiate (define) your variable somewhere. Maybe in your case, adding int Student::count; to your main file would be fine.

Unresolved external symbol on static class members

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