Consider the following struct:
struct Toto {
static int a;
static void Print() {
std::cout << a;
}
};
And the following main function using the struct in the same cpp file (main.cpp):
int main()
{
Toto::Print();
}
Building this gives the following error:
Error LNK2001 unresolved external symbol "public: static int Toto::a"
I understand from https://en.cppreference.com/w/cpp/language/static that
Static members of a class are not associated with the objects of the
class
And thus, I've been told we have to define the variable Toto::a outside the struct, in
the translation unit as follow:
int Toto::a;
From the same source it says that
Static member functions are not associated with any object.
And that
Static data members are not associated with any object.
Why do I have to define static variables but not static functions?
Static member functions are ordinary functions at the assembly level. The difference is only the hidden pointer 'this' that does not exist in them. They are basically global functions that exist like any other non static or non member (and not inline) function within the C++scope of a class name. Function scopes are C++ thing, they are not there at the CPU level.
Static variables are different. They exist before any class object is created. They are not created when a class instance is created. They are there as globals.
Perhaps it's done the way it's done to emphasize that difference.
I have a program where a class T has a static function.
static void T::func()
{
m_i=10;
cout<<m_i<<endl;
}
When I try to add static in function definition, the compiler throws error
error: cannot declare member function ‘static void T::func()’ to have static linkage.
Why is it not accepting static keyword in definition?
The problem is that the keyword static means different things depending on context.
When you declare a member function to be static, like in
class T
{
...
static void func();
...
};
Then the static keyword means that func is a class function, it's not bound to a specific object.
When you define the function in a source file, like
static void T::func() { ... }
Then you set the function linkage which is different from using static in a declaration inside a class. What static does when defining the function is to say that the function is only available in the current translation unit, and that contradicts the declaration that the function is available for all who knows the class.
It's simply not possible to make a member function (declared static or not) have static linkage.
If you want to "hide" the member function from others, so it can't be called, why not simply make it a private member function? You could also use things like the pimpl idiom or just not have it as a member function to begin with, in which case you can declare it to have static linkage.
You don't need static in implementation, only in definition.
T.h
class T
{
int m_i;
static int s_i;
public:
static void func();
};
T.cpp
int T:s_i = 0;
void T::func()
{
// Access only static and local variables
// I.e this is not allowed
m_i=10;
// This is allowed
s_i=10;
}
i have like 5 erros when trying to compile the code below.
it's like:THey are mainly pointing on static string rzym and static int arab.
the main errors:
In arab2rzym function:
- : invalid use of member ‘RzymArab::arab’ in static member function
- : error: from this location
- : error: invalid use of member ‘RzymArab::arab’ in static member function
- : invalid use of member ‘RzymArab::rzym’ in static member function
- : cannot declare member function ‘static std::string RzymArab::arab2rzym(int)’ to have static linkage [-fpermissive]
Here is the code:
#include <iostream>
#include <string>
using namespace std;
class RzymArab
{
private:
string rzym[13] = {"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};
int arab[13] = {1,4,5,9,10,40,50,90,100,400,500,900,1000};
public:
static int rzym2arab(string);
static string arab2rzym(int);
};
static string RzymArab::arab2rzym(int x)
{
int i=12;
string s="";
while(x>=1)
{
if(x>=arab[i])
{
x-=arab[i];
s=s+rzym[i];
}
else
i-=1;
}
return s;
}
int main()
{
string x;
x=RzymArab.arab2rzym(1164);
cout<<x<<endl;
return 0;
}
I would be grateful for helping!I tired some things but still bunch of errors. I want to use elements from class without creating an object.Any ideas?
You can't access non static class member variables from static member functions. You'll need to make them static also:
class RzymArab {
private:
static string rzym[13];
static int arab[13];
public:
static int rzym2arab(string);
static string arab2rzym(int);
};
Also those need to be defined separately (in your class' .cpp file usually):
string RzymArab::rzym[13] =
{"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};
int RzymArab::arab[13] = {1,4,5,9,10,40,50,90,100,400,500,900,1000};
Additionally note you don't use the static keyword for the (non inline) definition of your static function (it's invalid syntax). Just write:
string RzymArab::arab2rzym(int x) {
// ...
}
See the fully fixed, compilable and running sample here please.
The deal with class (also known as "static") vs. instance member functions is that an instance member function can access both static and instance members (variables and functions), while static member functions can access only static members. That is why you need to make the
int arab[13]; // The initializer needs to go into cpp file
string rzym[13];
member static in the class:
static int arab[13];
static string rzym[13];
The initializer needs to go to the cpp file:
// This goes into the CPP file
int RzymArab::arab[13] = {1,4,5,9,10,40,50,90,100,400,500,900,1000};
string RzymArab::rzym[13] = {"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};
Finally, you refer to static members with the scope resolution operator ::, not with a dot:
x=RzymArab::arab2rzym(1164);
I method that is declared static cannot access data members in the class.
Perhaps you should drop static everywhere?
You cannot access non-static members of a class from a static method of the same class without an object of that class. Non-static members exist only within the context of an object and cannot be access from static methods, that have class scope.
So you either:
make all members static
make all members non-static
pass an object to the static methods used to access the non-static members
Also notice that the static keyword is only necessary when declaring the function, not when you define it.
It isn't possible. A static method can only access other shared things (variables, other methods, etc.).
Example:
Say we have a Square class. You can create an object by passing the height and width into the constructor.
Square mySquare(2,2)
The Square class has a method for getting the area of the object. So you would call it as so:
double area = mySquare.getArea();
That works and all because you are using the instance variables for that specific object's height and width to calculate it. But lets say we want to calculate the area of a square before we create the object to make sure it's valid. So we would call the static getArea(double w, double h) method that is in the Square class.
double area = Square.getArea(2,4);
This works. But if you tried to call the getArea() method (that doesn't have parameters) would give you an error because it wouldn't know what height and width to use because they haven't been defined yet.
double area = Square.getArea(); //This will give you an error.
Hope this helps.
This question already has answers here:
Undefined reference to static class member
(9 answers)
Closed 9 years ago.
following compiles fine with g++:
struct acounter {
long static counter;
void static create() { //reset or create the counter
counter=0;
}
void static count() { //the counter changes its internal value.
counter=counter + 1;
}
};
int main(int argc, char *argv[] ){ //compiles and executes!
//do some random stuff...
return 0;
}
The problem is: as soon as I add "acounter::create();" or "acounter::count();" to the main loop, I get an error:
undefined reference to `acounter::counter'
But I defined "counter" and even initialize it. What is the problem?
(P.S. I can only use static functions as I have to deal with callbacks later - the idea is to use the whole struct only on its global scope without creating instances.)
Static class members need to be defined as well as declared. While we're at it, we can initialize the static member to the right value, so no more need for "create" - but we could feasibly have a "reset" logic.
Also, if you're actually exposing the logic via static functions, the counter itself should be private.
Finally, as a matter of style, the static keyword is usually placed before the type name. It's a matter of taste, but it's a rather important attribute and one should be able to quickly tell static and non-static members apart when looking at a class definition.
struct acounter
{
private:
static long counter;
public:
static void reset() { counter = 0; }
static void count() { ++counter; }
};
long acounter::counter = 0; // definition and initial value
int main()
{
acounter::count();
}
Put this into *.cpp:
long acounter::counter;
NOTE: You might want to initialize it as well, for example:
long acounter::counter = 0;
static, but non-const data members should be defined outside of the class/struct definition and inside the namespace enclosing the class/struct. The usual practice is to define it in the translation unit (*.cpp) because it is considered to be an implementation detail.
Extract from section 9.4.2 of the C++ Standard:
The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition.
There is also another way. Only static and const integral types can be declared and defined at the same time (inside class/struct definition):
class Example {
public:
static const long x = 101;
};
in this case you don't need to add x definition because it is already defined inside the class/struct definition. In your case, long is integral type, but not const so you cannot opt to this approach.
I have a class in foo.h containing a static member
class foo {
public:
static vector<int> a;
static void Init() { // Init a }
}
Everything works fine until I have a testing file
foo_test.cpp which is testing class foo. But in the
testing file, the static member a is not visible because
static member is only visible... How do I solve this?
Thanks
You will need to define a, in your cpp file add a line like:
vector<int> foo::a;
Edit: changed the data type to reflect the edit in the question
If you call foo::Init() outside the scope, you will get function re-declaration error. If you put it inside the scope, you will getting unresolved external symbol. You can only init it as int foo::a = 0;