why c++ does not accepts static keyword in function defnition? - c++

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;
}

Related

Why don't we have to declare static functions the same way we need to declare static variables in c++?

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.

Static function vs Static member functions C++

I've been reading a bit about static functions and static member functions. From my understanding if a function is declared static then this function is only visible to it's translation unit and nowhere else. A static member function instead is a function that can be called without instantiating any object of its class (so you can use it like it was in a name space).
To clarify with static function I mean something like
static int foo(int a, int b)
{
return a + b;
}
And with static member function I mean
struct MyClass
{
static int foo(int a, int b)
{
return a + b;
}
}
Is this the only difference? or is the visibility within the same translation unit still a common feature for the two of them?
As you can see on this page, static actually has 3 different meanings depending on where it's used.
If it's used inside a block scope, like inside a function, then it'll make a variable persist across function calls.
If a class method is declared as static, then it's not bound to a specific instance of the class.
If a namespace member is declared as static, then it has internal linkage only.

Member function with static linkage

I'm trying to understand why the following is an error:
class Foobar {
public:
static void do_something();
};
static void Foobar::do_something() {} // Error!
int main() {
Foobar::do_something();
}
This errors with "error: cannot declare member function 'static void Foobar::do_something()' to have static linkage" in g++, and "error: 'static' can only be specified inside the class definition" in clang++.
I understand that the way to fix this is to remove "static" in the definition of do_something on line 6. I don't, however, understand why this is an issue. Is it a mundane reason, such as "the C++ grammar dictates so", or is something more complicated going on?
The keyword static has several different meanings in C++, and the code you've written above uses them in two different ways.
In the context of member functions, static means "this member function does not have a receiver object. It's basically a normal function that's nested inside of the scope of the class."
In the context of function declarations, static means "this function is scoped only to this file and can't be called from other places."
When you implemented the function by writing
static void Foobar::do_something() {} // Error!
the compiler interpreted the static here to mean "I'm implementing this member function, and I want to make that function local just to this file." That's not allowed in C++ because it causes some confusion: if multiple different files all defined their own implementation of a member function and then declared them static to avoid collisions at linking, calling the same member function from different places would result in different behavior!
Fortunately, as you noted, there's an easy fix: just delete the static keyword from the definition:
void Foobar::do_something() {} // Should be good to go!
This is perfectly fine because the compiler already knows that do_something is a static member function, since you told it about that earlier on.
This question is already well answered. Details for static can be read here
Golden Rule:
The static keyword is only used with the declaration of a static member, inside the class definition, but not with the definition of that static member.
For future reference, to have the static method put the static method code above where it is called in the same file and define it as static. Also remove the class reference.
So instead of:
static void Foobar::do_something() {} // Error!
Use:
static void doSomething(){} // the Foobar is removed
It won't be able to access object values but just pass these in as parameters.

What is throwing the error the static or the const?

The following code is throwing an error message and I can't figure out what the issue is - is it the word static, or const? What am I doing wrong?
#include <iostream>
using namespace std;
class SampleClass
{
private:
int value;
static int counter;
public:
SampleClass(int i)
{
value = i;
counter++;
}
static int countSomeClass() const
{
return counter;
}
void showValue()
{
cout << value << endl;
}
};
int main()
{
SampleClass test(50);
test.showValue();
test.countSomeClass();
return 0;
}
Error message:
main.cpp:16:35: error: static member function static int SampleClass::countSomeClass() cannot have cv-qualifier
static int countSomeClass() const
A static method cannot be marked as const: since it doesn't work on an instance, it makes no sense to specify that it cannot modify it.
(you could argue that for static methods it could have referred to static methods that cannot modify the static data associated with the class; however, this would have no use anyway, since you cannot have a const class or form a const pointer or reference to a class, as in C++ classes aren't objects)
As the error message says, a static member function can't have a cv-qualifier - that is, a const or volatile qualifier. Such qualifiers are applied to this within a non-static member; they make no sense on a static member which has no this.
You want the function to be static, since it doesn't depend on any instance; so remove the const.
A static function cannot be const (cv-qualified) and vice-versa. It is the combination of the two that is the problem.
From the C++ specification § 9.4.1/2 (emphasis mine)
[ Note: A static member function does not have a this pointer (9.3.2). —end note ] A static member function shall not be virtual. There shall not be a static and a non-static member function with the same name and the same parameter types (13.1). A static member function shall not be declared const, volatile, or const volatile.
A static function has no this access since it is not associated with a specific instance of an object. There is no need for a const to be applied, it wouldn't make sense - there is no instance of an object to apply the const to. In a similar way, a free function cannot be const (or cv-qualified).
If you wish the function to be associated with an object, remove the static, if you want it to be static remove the const - from your sample, remove the const.
One more note; your counter is declared but not defined (outside the class). It requires something like int SampleClass::counter = 0; in one of the translation units (cpp file).
It's related to both.
A static member function does not work on an instance of the class it's a member of.
The const keyword at the end of a member function signature indicates that this member function does not modify the instance it's called on.
So it makes no sense (and is thus invalid) to have both in the same member function declaration.

Static function and non-static variable

In following code:
class A
{
public:
static void StaticFunction(int variable){ }
void NonStaticFunction() { }
private:
int nonStaticVariable;
};
I need to get a 'variable' and use it in 'NonStaticFunction'
I have tried making 'nonStaticVariable' static and assign its value to 'variable', but then I still would have to use static variable in 'NonStaticFunction', which throws linker error.
Error 2 error LNK2001: unresolved external symbol "public: static unsigned int A::staticVariable" (?staticVariable#A##2IA)
Are there any ways of solving it?
You need to add a definition for your static data member at namespace scope:
int A::nowStaticVariable; // Put an initializer if 0 is not OK for you
However, if your static function needs access to a non-static data member, and you're forced to make that data member static in order to make the whole thing work, that smells like bad design. Consider re-thinking it.
If you make nonStaticVariable static; i.e.
static int nonStaticVariable;
in your class then you need to provide storage for it (or the linker will complain). This is called the definition. Do this in a source file by writing
int A::nonStaticVariable;
Interestingly this is initialised to zero (unlike non-statics in C and C++ which are not initialised).
Conceptually, you need to do this because no object of class A instantiates the static variable since it's not an instance-level data member.
You don't have to use the parameter in your static function
class A
{
public:
static void StaticFunction(int // you don't need it ){ }
void NonStaticFunction() { }
private:// it can't be static and private ????
static int nonStaticVariable;
};
int A:: nonStaticVariable = 0 ;
void A::StaticFunction(/*int v */){
you can use directly your static variable and if you declared parameter in your function
v= nonStaticVariable;
}