How can static functions be useful? - c++

I don't get all these keywords. Specially this one static. An example of how important it is and how it used would be wonderful.

Making a member function static allows you to call the function without creating the class object.
class MyClass
{
int i;
static MyClass *ptr;
static MyClass* getInstance()
{
if(NULL == ptr)
{
ptr = new MyClass();
}
return ptr;
}
};
MyClass* MyClass::ptr = NULL;
int main()
{
MyClass *ptr = MyClass::getInstance();
}
Check out the Singleton pattern for more information on how it can be helpful.

static member functions are just like regular functions.
class Sample
{
public:
static void DoWork()
{
cout << "Static Member Function"<< endl;
}
};
//access
Sample::DoWork();
Output:
Static Member Function
You can treat them just like regular functions, that means, you can pass them to other functions which accept only regular function as argument, like this:
typedef void (*Worker)();
void Fun(Worker worker)
{
//call here just like regular function
worker(); //note: class name is not needed even if you pass static member function!
}
//pass static member function!!
Fun(Sample::DoWork);
Output:
Static Member Function

There are multiple uses for the static keyword, it does different things based on where you use it.
http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx
When you declare a variable or
function at file scope (global and/or
namespace scope), the static keyword
specifies that the variable or
function has internal linkage. When
you declare a variable, the variable
has static duration and the compiler
initializes it to 0 unless you specify
another value.
When you declare a variable in a
function, the static keyword specifies
that the variable retains its state
between calls to that function.
When you declare a data member in a
class declaration, the static keyword
specifies that one copy of the member
is shared by all instances of the
class. A static data member must be
defined at file scope. An integral
data member that you declare as const
static can have an initializer.
When you declare a member function in
a class declaration, the static
keyword specifies that the function is
shared by all instances of the class.
A static member function cannot access
an instance member because the
function does not have an implicit
this pointer. To access an instance
member, declare the function with a
parameter that is an instance pointer
or reference.

Static classes and class members are used to create data and functions that can be accessed without creating an instance of the class. The advantage is that you don't need to instantiate the class to use methods or properties.
An example of when to use a static class might be for utility functions such as converters (e.g. Fahrenheit to Celcius). This type function doesn't change irregardless of any object or data.
In C# you can call a static method like this:
double F, C = 0
// TempConverter converter = new TempConverter(); <-- NOT NEEDED FOR STATIC
F = TempConverter.CelsiusToFahrenheit("100.0");
C = TempConverter.FahrenheitToCelcius("212.0");
Here is how the static class and methods are defined:
public static class TemperatureConverter {
public static double CelsiusToFahrenheit(string temperatureCelsius) {
.. conversion code..
}
public static double FahrenheitToCelsius(string temperatureFahrenheit) {
.. conversion code..
}
}

There are two types of static functions: class/struct member, and non-member. I guess you're wondering about the former (as it's more confusing)...
static member functions
If we contrast four functions:
class X
{
....
int non_static_member_f(X& a) { ... }
static int static_member_f(X& a) { ... }
friend int non_member_friend_f(X& a) { ... }
};
int non_member_f(X& a) { ... }
And given:
X x, arg;
We can write:
x.non_static_member_f(arg) - x is an existing X object instance - made accessible via the this pointer. The function has full access to all private/protected/public static/non-static members of X for operations on x and arg.
X::static_member_f(arg) can be invoked with a single X argument - if the function didn't specify an X argument, then it could be called with no existing X objects. It has full access to all private/protected/public static of X, and can access any non-static members on arg.
non_member_friend_f(arg) has the same access as X::static_member_f(arg), but is not scoped inside X (i.e. you don't need to call it with the X:: prefix, Koenig lookup resolves differently).
non_member_f(arg) can only access the public members of arg, and has no special privileges.
For completeness: static non-member functions differ from non-static in having internal linkage, which means they're not callable from other translation units but won't clash with any same-named function in those translation units.

Static functions are very useful when implementing so-called Named Constructors.
Imagine a Point class which can be either constructed from rectangular coordinates (X/Y) or polar coordinates (radius and angle):
class Point {
public:
Point(float x, float y); // Rectangular coordinates
Point(float r, float a); // Polar coordinates (radius and angle)
// ERROR: Overload is Ambiguous: Point::Point(float,float)
};
int main()
{
Point p = Point(5.7, 1.2); // Ambiguous: Which coordinate system?
...
}
This can be solved very nicely using static functions which create Point objects; such functions are called named constructors since they act like a constructor (they produce a new object) but they can have a descriptive name:
class Point {
public:
// These static methods are the so-called "named constructors"
static Point rectangular(float x, float y) { return Point(x, y); }
static Point polar(float radius, float angle) { return Point(radius*std::cos(angle), radius*std::sin(angle)); }
// ...
private:
Point(float x, float y) : x_(x), y_(y) { }
float x_, y_;
};
Clients of the class can now use these named constructors to create readable, unambiguous code:
int main()
{
Point p1 = Point::rectangular(5.7, 1.2); // Obviously rectangular
Point p2 = Point::polar(5.7, 1.2); // Obviously polar
}
Furthremore, named constructors can be used to make sure that objects of a class are always allocated with new (so that you know that you can always call delete on them). See FAQ [16.21] for more information.

static class member functions are useful:
For implementing the Factory Method Pattern
For implementing the Singleton Pattern
For loose decoupling of functions that may polute the behaviour of the class. ( Functions not necessarily members can be declared static... but even better they could be totally classic functions!) cf S.R.P.
Can be used as a function to be passed as a plain C function pointer so as to inter-operate with C code...
static functions are useful:
1. to avoid duplicate code redefinition while compiling. A static function will be redefined for each cpp unit it is included in.
And I think there are tons of other useful cases I don't remember of right now :-)

The answer from martona is a good overview of static. Relating to static members, I think Tony covers it pretty well.
The mental model I use when it comes to member functions is to consider how they might be modeled in 'C':
class A
{
public:
void mbr_1 ();
void mbr_2 () const;
void mbr_3 () volatile;
void mbr_4 () const volatile;
static void mbr_5 ();
};
Might be implemented as:
struct A { };
void mbr_1 (A * const this);
void mbr_2 (A const * const this);
void mbr_3 (A volatile * const this);
void mbr_4 (A const volatile * const this);
void mbr_5 ();
All the funcitons are members and so have appropriate 'access' to private members. The non static members have a 'this' pointer, and it is that which provides the access to a specific instances members. The static member doesn't have such a pointer and this is why we cannot access any non static members.

Related

Invalid use of this in a non static member function

I got the following class:
class Foo {
private:
static float scale;
public:
static float setScale(float scale);
};
When I am trying to implement setScale like this:
float Foo::setScale(float scale) {
this->scale = scale;
return scale;
}
It throws an error:
Invalid use of 'this' outside of a non-static member function.
I really don't get this since my function is marked static.
I saw some related questions but it didn't answer my question.
So how can I fix this?
I know I can change the names and don't use this but there probably is a solution for this?
EDIT: Also when I implement the function inside the class it still throws the same error.
A static member function is not part of the class. In other words, there is only one instance of it. Notice how you access them using the scope resolution operator(Foo::setscale(1.f);), instead of the member reference operator(Foo.setscale(1.f)), because they are not members of instances of the class.
class Foo
{
public:
void DoSomething();
};
In this example, if I create a Foo f and call f.DoSomething(), what happens is that the compiler actually transforms DoSomething() into DoSomething(Foo* this) where this is the address of f.
However, since static member functions are not part of the class, the compiler does not transform them to take in a this pointer.
P.S. So why have static member functions? For one, you can limit the scope of the function to the class it is declared in.
Thank you for reading.
this pointer is not there in static member functions of class. Change the definition as follows:-
float Foo::setScale(float s) {
Foo::scale = s;
return s;
}
Change the function definition the following way
float Foo::setScale(float scale) {
Foo::scale = scale;
}
static member functions have no implicit parameter this.
In the note of paragraph #2 of section 9.4.1 Static member functions of the C++ Standard there is explicitly written that
2 [ Note: A static member function does not have a this pointer
(9.3.2). —end note ]
Also you have to define the function as having return type void because at least you are returning nothing from the function.
void Foo::setScale(float scale) {
Foo::scale = scale;
}

How to make C++ class access ALL of another class's private members in a const way (only read not write)

I'm making a game where I have a Level class that deals with storing all the objects in vectors and changing them.
And I have another class that is called Engine.h that has static functions that calculate things based on the vectors Level owns but doesn't change anything in them. Level calls the Engine functions and does operations based on what's returned.
But since Engine needs to see the vectors that Level owns, I'm being forced to pass a bunch of pointers (const) of vectors to each Engine function so that it can do calculations based on the current state of the vectors.
Is there any way to make Engine just have access to all of Level's member variables but not be able to edit any of them. Some sort of a 'const friend"?
I just realized that there is an object level. So I also would need to have a way to assign Engine a specific object of Level with which it could be a 'const friend'.
Maybe this got to complicated. If there is no solution is it bad practice to pass a lot of member variables to the Engine functions, or is that how this is done. What about passing a pointer to Level that is const (will that make all of Levels member variables const also?)
Lets say you have some class Foo that has a member variable x you want to access. You can make const functions that access the member variables by value. Since they are const, they may not modify any of the member variables.
class Foo
{
public:
Foo() : x{0} {} // constructor
int getX() const { return x; } // this is a "getter"
void setX(int value) { x = value; } // this is a "setter"
private:
int x;
};
Then you can have your other class Bar. Maybe in some function it needs to access to x variable of Foo, you can use the getter.
class Bar
{
void doStuff (Foo a)
{
int answer = a.getX();
std::cout << answer << std::endl;
}
};
Now we can look at a quick demo. We make an instance of Foo and an instance of Bar. Then we can set the x value for the Foo, and access it from Bar's doStuff function.
int main()
{
Bar myBar;
Foo myFoo;
myFoo.setX(5);
myBar.doStuff(myFoo); // will output 5
return 0;
}
You can do stuff like this if it helps:
class Level
{
private:
std::vector<float> stuff;
public:
// give outsiders const access
const std::vector<float>& const_stuff = stuff; // c++11 else use ctor
const std::vector<float>& get_stuff() const { return stuff; } // more idiomatic
};

Does pointer-to-member make sense for a static member?

The pointer-to-member feature of C++ is interesting and powerful, but I'm wondering if it is or should be limited only to instantiated objects of a class, or if it is okay to point to a static member? The use cases aren't obvious to me for either static or non-static usage of the feature, though it does seem very interesting.
Pointers to statics are actually "normal" pointers, e.g.
class MyClass
{
public:
static int x;
static int f(int a)
{
return a+1;
}
};
// ...
int* pint = &MyClass::x; // pointer to static property
int (*pfunc)(int) = &MyClass::f; // pointer to static method
Pointers to non-static members are "special" because they need a class instance to dereference a value. They can be thought of as "offset of a member inside a class instance" (this is very rough, though, and cannot be applied to method pointers!).
Static members, on contrast, are actually much like namespaced global variables, possibly with restricted visibility. They have static memory addresses, which are independent of class instances — all instances share a single static member.
The following is legal C++11 code.
struct X
{
static void f() {}
static int i;
X() = delete;
};
typedef void(*funcPtr)();
int main()
{
funcPtr g = &X::f;
int * j = &X::i;
}
There is nothing wrong about taking adresses of static member data and functions. As you can see the class never gets instantiated at any time.

Why do I have to put this function static

I am trying t understand the Named Constructor Idiom in the example I have
Point.h
class Point
{
public:
static Point rectangular(float x, float y);
private:
Point(float x, float y);
float x_, y_;
};
inline Point::Point(float x, float y) : x_(x), y_(y) {}
inline Point Point::rectangular(float x, float y) {return Point(x,y);}
main.cpp
#include <iostream>
#include "include\Point.h"
using namespace std;
int main()
{
Point p1 = Point::rectangular(2,3.1);
return 0;
}
It does not compile If Point::rectangular is not static and I don't understand why...
In this context, the static keyword in front of a function means that this function does not belong to any particular instance of the class. Normal class methods have an implicit this parameter that allow you to access the members of that specific object. However static member functions do not have the implicit this parameter. Essentially, a static functions is the same as a free function, except it has access to the protected and private members of the class it is declared in.
This means you can call static functions without an instance of that class. Instead of needing something like
Point p1;
p1.foo();
You simply do this:
Point::foo();
If you tried to call a non static function like this, the compiler will complain, because non-static functions need some value to assign to the implicit this parameter, and Point::foo() doesn't supply such a value.
Now the reason you want rectangular(int, int) to be static is because it is used for constructing a new Point object from scratch. You do not not need an existing Point object to construct the new point so it makes sense to declare the function static.

Illegal call to non-static member function (C++)?

I'm developing a game which is based around the user controlling a ball which moves between areas on the screen. The 'map' for the screen is defined in the file ThreeDCubeGame.cpp:
char m_acMapData[MAP_WIDTH][MAP_HEIGHT];
The ThreeDCubeGame.cpp handles most of the stuff to do with the map, but the player (and keyboard input) is controlled by ThreeDCubePlayer.cpp. When a player moves into a new map cell, the game will have to check the contents of that cell and act accordingly. This function in ThreeDCubeGame.cpp is what I am trying to use:
inline char GetMapEntry( int iMapX, int iMapY ) { return m_acMapData[iMapX][iMapY]; }
So, in order to check whether the player is allowed to move into a map cell I use this function call from ThreeDCubePlayer.cpp:
if (ThreeDCubeGame::GetMapEntry(m_iMapX+MAP_OFF_X, m_iMapY+MAP_OFF_Y) == ' ')
{
// do stuff
}
But, when I compile this, I get the warning "error C2352: 'ThreeDCubeGame::GetMapEntry' : illegal call of non-static member function". Is this something to do with the scope of the variables? Is it fixable without redesigning all the code?
class A {
int i;
public:
A(): i(0) {}
int get() const { return i; }
};
int main() {
A a;
a.get(); // works
A::get(); // error C2352
}
There's no object to call the function with.
GetMapEntry is not static so you can't call it without an object of the type ThreeDCubeGame.
Alternatives:
-Make GetMapEntry static: static inline char GetMapEntry
-Create an instance of ThreeDCubeGame and do instance.GetMapEntry(
ThreeDCubeGame is a class, not an instance, thus you can only use it to access static members (that is, member function with the keyword static)
You have to instantiate an object of this class to use non-static members
ThreeDCubeGame map;
...
map.GetMapEntry(iMapX, iMapY).
You are trying to call a class method. Is that what you intend? Or do you mean for GetMapEntry to be an instance method? If it's a class method, it needs to be marked static. If it's an instance method, you need to call it with an instance of ThreeDCubeGame. Also, is GetMapEntry even a member of a class?
The error indicates that your are calling the GetMapEntry function as a static one whereas you have declare it as a member function. You need to:
call it via an instance of ThreeDCubeGame: threedcubegameinstance.GetMapEntry(),
declare the GetMapEntry function as static (add a static before inline and make m_acMapData static too).
You're missing the "static" keyword.
// .h
class Playfield
{
public:
static char GetTile( int x, int y );
// static on a method means no 'this' is involved
};
// .cpp
static char tiles[10][10] = {};
// static on vars in .cpp prevents access from outside this .cpp
char Playfield::GetTile( int x, int y )
{
// handle invalid args
// return tile
return tiles[x][y];
}
There's other options if you want only one unique playfield:
You can make Playfield a singleton, turn it into a namespace or use global functions.
The result is the same from the caller's point of view.
On a side note:
Since all of these use a static and/or global variable it's inherently not thread-safe.
If you require multiple playfields and/or want to play safe with multi-threadding and/or want to absolutely do it in an OOP fashion, you will need an instance of Playfield to call the function on (the 'this' pointer):
class Playfield
{
public:
char GetTile( int x, int y ) const { return this->tiles[x][y]; }
// you can omit 'this->', but it's inherently present because
// the method is not marked as static
public:
Playfield()
{ /*you will have to initialize 'this->tiles' here because
you cannot use the struct initializer '= {}' on member vars*/ }
private:
char tiles[10][10];
};
The calling code would use Playfield like this:
void main()
{
// static version
char tile11 = Playfield::GetTile( 1, 1 );
// non-static version
Playfield myPlayfield;
char tile12 = myPlayfield.GetTile( 1, 2 );
}
It can be useful to have a class containing a collection of functions, without any data members, if you don't want to expose the helper-functions.
Otherwise it would be more practical to use a namespace to collect these functions in.
Example:
class Solvers
{
public:
void solve_a(std::vector<int> data);
void solve_b(std::vector<int> data, int value);
private:
int helper_a(int a, int b);
}
But a class needs to be initialised before use.
The simplest way to make these functions usable would be to mark them static in the class:
static void solve_a(std::vector<int> data);
Then the member-functions can be used as:
Solver::solve_a(my_vector);
Another way would be to initialise the class before using:
Solver solver;
solver.solve_a(my_vector);
And the third method, not mentioned before, is by default initialising it during use:
Solver().solve_a(my_vector);