Error LNK2001 in Visual Studio 2017 when using static int [duplicate] - c++

This question already has answers here:
How to initialize private static members in C++?
(18 answers)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 3 years ago.
I'm doing some practice tasks for uni and I'm supposed to create static int field inside a class, but when I do so I get error LNK2001. When I change it to regular int the error does not occure. Can anybody help me please? Here's my code:
#include <iostream>
#include <string>
using namespace std;
class Uczelnia {
public:
virtual string getName() = 0;
static int liczba_wszystkich_studentow;
};
class Politechnika:public Uczelnia {
public:
Politechnika(string a, int b) {
nazwa = a;
liczba_studentow = b;
liczba_wszystkich_studentow = +liczba_studentow;
}
string getName() {
cout << "Politechnika: " << nazwa << endl;
return nazwa;
}
~Politechnika() {
liczba_wszystkich_studentow = -liczba_studentow;
}
private:
string nazwa;
int liczba_studentow;
};
class Uniwersytet :public Uczelnia {
public:
Uniwersytet(string a, int b) {
nazwa = a;
liczba_studentow = b;
liczba_wszystkich_studentow = +liczba_studentow;
}
string getName() {
cout << "Uniwersytet: " << nazwa << endl;
return nazwa;
}
~Uniwersytet() {
liczba_wszystkich_studentow = -liczba_studentow;
}
private:
string nazwa;
int liczba_studentow;
};
int main() {
Politechnika p1("Warszawska", 200);
p1.getName();
Uniwersytet u1("Warszawski", 600);
}

You're getting a linker error because you haven't initialized the static member.
You just need to initialize it outside of the class.
class Uczelnia {
public:
//..
static int liczba_wszystkich_studentow;
//..
};
int Uczelnia::liczba_wszystkich_studentow = 5;
There are some additional intricacies of being able to initialize static const integral types (like int) inside of the class, but with others you would typically initialize these static members in the source file outside of the class definition.

Within a class definition there are declarations of static data members not their definitions. Declared static data members within a class definition may even have an incomplete type. If a static data member is ODR used it shall be defined outside a class definition in some module. For example
int Uczelnia::liczba_wszystkich_studentow;
In C++ 17 you can use the inline specifier in a declaration of a static data member within a class definition.
For example
class Uczelnia {
public:
virtual string getName() = 0;
inline static int liczba_wszystkich_studentow;
};
In this case the code will compile provided that the compiler supports C++ 17..

Related

Why can I not set a value for static variable inside the class?

I am new to c++ and experimenting with classes and static variables.
I have found the solution to making the code run but I am not sure why this works and why my previous method did not
#include <iostream>
using namespace std;
class Person {
static int id;
public:
void createPerson() {
id++;
cout << id << endl;
}
};
int Person::id = 0;
int main() {
Person Person1;
Person Person2;
Person1.createPerson();
Person2.createPerson();
}
I am wondering why I must declare the value of id outside the class. And why I cannot have something like..
class Person {
static int id = 0;
public:
void createPerson() {
id++;
cout << id << endl;
}
};
static data members are not parts of objects, so you need to tell the compiler explicitly in which translation unit to store them by providing that definition.
Note that static data members of class templates can be defined in the header files.
In C++17 a static data member can be declared as inline, so that no out-of-line definition is necessary.
Adding the inline keyword will do the job. Simply change your line to:
static inline int id = 0;
Another possibility would be, but only if your value is constant, to declare it like this:
static inline constexpr int id = 0;
This is the preferred way for declaring global constants instead of using #defines.
Within a class definition static data members are declared bur not defined. So you may even to use a non-complete type in a declaration of a static data member inside a class definition.
For example
struct A
{
static int a[];
};
int A::a[10];
Here in this example the declaration of the data member a within the class definition has an incomplete array type (the number of elements of the array is unknown).
Starting from C++ 17 you may declare a static data member as an inline member. For example
class Person {
inline static int id = 0;
public:
void createPerson() {
id++;
cout << id << endl;
}
};
In this case you may initialize it in the declaration inside the class definition.
Otherwise you may initialize a static data member within a class definition only if it is declared as having an integral type and has the qualifier const or the specifier constexpr (in the last case the static data member will be an inline declaration).
But if a static data member is declared as a const object nevertheless you have to define it outside the class if for example you will try to get the address of the static data member. For example this code is invalid
#include <iostream>
using namespace std;
class Person {
const static int id = 0;
public:
void createPerson() {
cout << &id << endl;
}
};
int main()
{
Person Person1;
Person Person2;
Person1.createPerson();
Person2.createPerson();
}
As there is the address of the static data member is taken then you have to define the static data member.
#include <iostream>
using namespace std;
class Person {
const static int id = 0;
public:
void createPerson() {
cout << &id << endl;
}
};
const int Person::id;
int main()
{
Person Person1;
Person Person2;
Person1.createPerson();
Person2.createPerson();
}
This program will compile.

C++ const static member is not identified when trying to use it to initialize an array

I want to create a constant static int variable to specify the range of an array. I'm running into problems and getting errors saying that the variable is not a member of the class, but I can print out the variable in main using ClassName::staticVarName.
I cannot figure out how to properly set up a static variable that belongs to a class so that it can be used to initialize an array. The variable prints in main, but for some reason it will not compile when I try to use it to define a classes's array field's range.
error: class "RisingSunPuzzle" has no member "rows"
error: class "RisingSunPuzzle" has no member "cols"
header file for class:
#pragma once
#include<map>
#include<string>
#include<memory>
class RisingSunPuzzle
{
private:
bool board[RisingSunPuzzle::rows][RisingSunPuzzle::cols];
public:
RisingSunPuzzle();
~RisingSunPuzzle();
static const int cols;
static const int rows;
void solvePuzzle();
void clearboard();
};
cpp file for class:
#include "RisingSunPuzzle.h"
const int RisingSunPuzzle::cols = 5;
const int RisingSunPuzzle::rows = 4;
RisingSunPuzzle::RisingSunPuzzle()
{
}
RisingSunPuzzle::~RisingSunPuzzle()
{
}
void RisingSunPuzzle::solvePuzzle()
{
}
void RisingSunPuzzle::clearboard()
{
}
The names of data members that are referred to must be declared before the data members that refer them to.
Also the static constants have to be initializes.
You can reformat the class the following way
class RisingSunPuzzle
{
public:
static const int cols = 5;
static const int rows = 4;
private:
bool board[RisingSunPuzzle::rows][RisingSunPuzzle::cols];
public:
RisingSunPuzzle();
~RisingSunPuzzle();
void solvePuzzle();
void clearboard();
};
//...
There is no need to define the constants if they are not ODR used. Nevertheless you can define them (without initializers) like
const int RisingSunPuzzle::cols;
const int RisingSunPuzzle::rows;

I have error in program to count total number of objects with static variable [duplicate]

This question already has answers here:
Member function with static linkage
(3 answers)
Closed 6 years ago.
using namespace std;
class Sample
{ int x;
static int count;
public:
void get();
static void showCount();
};
void Sample::get()
{
cin>>x;
++count;
}
static void Sample::showCount(){
cout<<"Total No. of Objects :"<<count;
}
int main()
{ Sample s1,s2;
s1.get();
s2.get();
Sample::showCount();
return 0;
}
Compilation Error :[Error] cannot declare member function 'static void Sample::showCount()' to have static linkage[-fpermissive]
Remove static keyword
void Sample::showCount(){
cout<<"Total No. of Objects :"<<count;
}
static keyword in a class member function declaration has a different meaning to static keyword in a function definition. The former tells that the function doesn't need an instance of the class (doesn't get this pointer), the later defines static linkage: local to the file, the function is accessible in this particular file only.
You are also missing definition of count. You need a line somewhere before main:
int Sample::count = 0;
...
main() {
...
}
class Sample
{ ...
static void showCount();
};
static void Sample::showCount(){
cout<<"Total No. of Objects :"<<count;
}
// You can void instead of static, because you are not returning anything.
This is incorrect. You don't need 2nd static.
When declaring static member functions in C++, you only declare it as static inside the class definition. If you implement the function outside the class definition (like you have), don't use the static keyword there.
Outside of a class definition, the static keyword on a function or variable means that the symbol should have "static linkage." This means that it can only be accessed within the source file (translation unit) that it's in. static symbols aren't shared when all of your compiled source files are linked together.
See this SO question if you aren't familiar with the term "translation unit."
You have one other problem, which Saurav Sahu mentioned: you declared the static variable static int count; but never defined it. Add this outside of the class definition:
int Sample::count = 0;
#include <iostream>
using namespace std;
class Sample
{
int x;
public:
static int count;
void get();
static void showCount();
};
int Sample::count = 0;
void Sample::get()
{
cin >> x;
++count;
}
void Sample::showCount(){
cout << "Total No. of Objects :" << count;
}
int main()
{
Sample s1, s2;
s1.get();
s2.get();
Sample::showCount();
return 0;
}

C++ static functions and variables

I have written a class as shown below:
#include<iostream>
using namespace std;
class A
{
static int cnt;
static void inc()
{
cnt++;
}
int a;
public:
A(){ inc(); }
};
int main()
{
A d;
return 0;
}
I want to call the function inc through the constructor, but when i compile i am getting an error as:
/tmp/ccWR1moH.o: In function `A::inc()':
s.cpp:(.text._ZN1A3incEv[A::inc()]+0x6): undefined reference to `A::cnt'
s.cpp:(.text._ZN1A3incEv[A::inc()]+0xf): undefined reference to `A::cnt'
I am unable to understand what the error is... plz help...
Static field is not defined - Take a look at Why are classes with static data members getting linker errors?.
#include<iostream>
using namespace std;
class A
{
static int cnt;
static void inc(){
cnt++;
}
int a;
public:
A(){ inc(); }
};
int A::cnt; //<---- HERE
int main()
{
A d;
return 0;
}
Inside the class static int cnt; is only declared, and need to be defined. In C++ you usually declare in your .h .hpp files and then define your static class members in your .c and .cpp files.
In your case, you need to add
int A::cnt=0; // = 0 Would be better, otherwise you're accessing an uninitialized variable.

Pointer to static member variable [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++: undefined reference to static class member
The following C++ code compiles well (using g++ -c) but it doesn't link giving the error: undefined reference toAbc::X'`
#include <iostream>
using namespace std;
class Abc {
public:
const static int X = 99;
};
int main()
{
Abc a1;
cout << &(Abc::X) << endl;
}
I want to know why this is not allowed?
You need to have that static member actually defined, not just declared...
Add this line before your main():
const int Abc::X = 99;
As of C++17 you can also do an inline static, in which case the above additional line of code in a .cpp file is not needed:
class Abc {
public:
inline const static int X = 99; // <-- "inline"
};
If the static member is used in a way which requires an lvalue (i.e. in a way that requires it to have an address) then it must have a definition. See the explanation at the GCC wiki, which includes references to the standard and how to fix it.
If you don't like to think about translation units, static initialization order and stuff like that, just change your static constants into methods.
#include <iostream>
using namespace std;
class Abc {
public:
inline static const int& X(){
static int x=99;
return x;
}
};
int main()
{
// Abc a1;
cout << &(Abc::X()) << endl;
}