c++ accessing static member function with member-selection operator (. or –>) - c++

I just noticed that we can access c++ static member function by member-selection operator (. or –>)
for example:
class StaticTest
{
private:
int y;
static int x;
public:
StaticTest():y(100){
}
static int count()
{
return x;
}
int GetY(){return y;}
void SetY(){
y = this->count(); //#1 accessing with -> operator
}
};
Here are how to use
StaticTest test;
printf_s("%d\n", StaticTest::count()); //#2
printf_s("%d\n", test.GetY());
printf_s("%d\n", test.count()); //#3 accessing with . operator
test.SetY();
what is the use case of #1 and #3?
what is the difference between #2 and #3?
Another style of #1 for accessing static member function in member function is
void SetY(){
y = count(); //however, I regard it as
} // StaticTest::count()
But now it looks more like this->count(). Is there any difference of two style calling?
Thanks

Have a look at this question.
According to the standard (C++03, 9.4 static members):
A static member s of class X may be referred to using the qualified-id
expression X::s; it is not necessary to use the class member access
syntax (5.2.5) to refer to a static member. A static member may be
referred to using the class member access syntax, in which case the
object-expression is evaluated.
So, when you already have an object and you're calling a static method on it, then there is no difference to using the class member access syntax.
If you however need to create the object first (be it by instantiating the object directly before, or by calling some function), then this creation process will of course take up a little extra time and memory. The this-Pointer, however, is never passed in to a static function, the call itself is always the same, no matter how it was written.

I'm a little confused about the answer to your first question, but with regards to your second question:
in #2 ( StaticTest::count() ), you used the count() method in a static manner, which means you called the function without creating a StaticTest object.
in #3 (test.count()), you created a StaticTest object called test, and called the method through the object (even though it was unnecessary.)
Functionally, there is no difference, but #2 is the preferred way of calling StaticMethods. Making an object when it is not needed is bad use of memory.

C++03, 9.4 static members
A static member s of class X may be referred to using the qualified-id expression X::s; it is not necessary to use the class
member access syntax (5.2.5) to refer to a static member. A static
member may be referred to using the class member access syntax, in
which case the object-expression is evaluated.

Related

Why can't I pass the this pointer explicitly to a member function?

The c++ standard (ISO c++11) mentions in Section 9.3.1 that
A non-static member function may be called for an object of its class
type, or for an object of a class derived (Clause 10) from its class
type, using the class member access syntax (5.2.5, 13.3.1.1).
An attempt to compile this code with g++ (version 4.8.2)
class foo{
public:
void bar(){
cout<<"hey there"<<endl;
}
};
int main(){
foo obj;
foo::bar(&obj);
}
gives a compile time error because it couldn't match the function's signature. I guess that is expected given what the standard states about calling member functions.
Since the method will eventually take a form similar to bar(foo*) during some stage of compilation, why does the standard asks for member access syntax to call the member function?
Lets add a static member to the class as:
class foo{
public:
void bar() { cout<<"hey there"<<endl; }
static void bar(foo*) { cout<<"STATIC MEMBER"<<endl; }
};
Now if you write this:
foo::bar(&obj); //static or non-static?
Which function should be called? In such situation, how would you call both of them? What would be the syntax? If you allow one function to have this syntax, you've to abandon it (i.e syntax) for other function. The Standard decided to have foo::bar(&obj) syntax for static member function, while abandoning it for non-static member function.
Anyway, if you want to pass &obj as argument to the non-static member function, then you can use type-erasure facilitated by std::function as:
void (foo::*pbar)() = &foo::bar; //non-static member function #1
std::function<void(foo*)> bar(pbar);
bar(&obj); //same as obj.bar();
Likewise, you could call static member function as:
void (*pbar)(foo*) = &foo::bar; //static member function #2
std::function<void(foo*)> bar(pbar);
bar(&obj); //same as foo::bar(&obj);
Note that at lines #1 and #2, the types of the object pbar makes the compiler to choose the correct member function — in the first case, it takes the pointer to the non-static member-function while in the latter case, it takes the pointer to the static member function.
Hope that helps.

Using static function in class where a variable depends on constructor

Lets say I have a class with a static function. This function is called as static by another part of the code, without instantiating a class object. However, this static function also has in its code a dependance on variable x. x, however, is only initialized to a certain value or cleared in the constructor. But, given that no object of the class is instantiated, I believe that the variable is undefined. So, I have a few questions:
1) Is the constructor called at all?
2) Is the variable x undefined?
How can I work around a case like that?
In the example below, i'd want y to be 25, but can it ever be?
class CExample
{
public:
CExample(void);
~CExample(void);
static void foo();
int x;
};
CExample::CExample()
{
x = 5;
}
void CExample::foo()
{
int y = x*5;
}
Your code doesn't compile since the static function is using a variable which will only exist in objects instantiated by the class.
I'm not sure you've understood static. Only one static function exist. You can call it from anywhere. Which instance if CExample's x is it supposed to use?
This looks like a case of bad design. You could fix it so that it compiles by making x static and initialising it with 5. However you are probably a lot of better rethinking your design and what you want it to do. Remember there is only ever one instance of something that is static but there are as many instances of CExample as times you call it's constructor.
A static member function is a service of the class, not of a specific object of the class. A class's static data members and static member functions exist independently of instantiation of a object of that class.
The use of a static function will not call the constructor of its respective class, therefore your variable will not exist, causing a compilation error.
Just remember static member functions exist and operate independently of any objects of the class.
It's illegal to access a non-static member from a static function. See the output of gcc when I try to compile your program:
test.cpp: In static member function ‘static void CExample::foo()’:
test.cpp:9: error: invalid use of member ‘CExample::x’ in static member function

Why is calling a static member function with . or -> syntax legal? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ Static member method call on class instance
Today I discovered that something I had long (and I mean long—like, for twenty years), thought illegal in C++ is actually legal. Namely, calling a static member function as if it belonged to an individual object. For example:
struct Foo
{
static void bar() { cout << "Whatever."; }
};
void caller()
{
Foo foo;
foo.bar(); // Legal -- what?
}
I normally see static member functions being called strictly with "scope resolution syntax," thus:
Foo::bar();
This makes sense, because a static member function is not associated with any particular instance of the class, and therefore we wouldn't expect a particular instance to be syntactically "attached" to the function call.
Yet I discovered today that GCC 4.2, GCC 4.7.1, and Clang 3.1 (as a random sampling of compilers) accept the former syntax, as well as:
Foo* foo = new Foo;
foo->bar();
In my particular case, the legality of this expression led to a runtime error, which convinced me that the peculiarity of this syntax is of more than academic interest—it has practical consequences.
Why does C++ allow static member functions to be called as if they were direct members of individual objects—that is, by using the . or -> syntax attached to an object instance?
In The Design and Evolution of C++ at page 288, Bjarne Stroustrup mentions that in the days before static member functions, programmers used hacks like ((X*)0)->f() to call member functions that didn't need an object. My guess is that when static member functions were added to the language, access through -> was allowed so that programmers with code like that could change f to static without having to hunt down and change every use of it.
Presumably so you can call it in places where you may not know the class type of something but the compiler does.
Say I had a bunch of classes that each has a static member that returned the class name:
class Foo
{
static const char* ClassName() { return "Foo"; }
};
class Bar
{
static const char* ClassName() { return "Bar"; }
};
Then all over my code I could do things like:
Foo foo;
printf( "This is a %s\n", foo.ClassName() );
Without having to worry about knowing the class of my objects all the time. This would be very convenient when writing templates for example.
It's like this because the standard says that's how it works. n3290 § 9.4 states:
A static member s of class X may be referred to using the qualified-id
expression X::s; it is not necessary to use the class member access
syntax (5.2.5) to refer to a static member. A static member may be
referred to using the class member access syntax, in which case the
object expression is evaluated. [ Example:
struct process {
static void reschedule();
};
process& g();
void f() {
process::reschedule(); // OK: no object necessary
g().reschedule(); // g() is called
}
end example ]
From The Evolution of C++ (pdf), section 8. Static Member Functions:
...It was also observed that nonportable code, such as
((x*)0)->f();
was used to simulate static member functions.
So my guess is (based on the pattern of rationale for almost every other weird syntactical thing) they allowed invoking a static member function when you just had the type to provide backwards compatibility with an established but broken idiom.
If you don't subscribe to the "because the standard says so" school of causality, I also suggest that static methods are old enough to come from a time when people actually worried about the extra overhead from passing the this argument to a function call, so making pure functions "static" as an optimization was probably all the rage in 1985.

static member functions and thread-safety

Objects and variables created in a static member function are not considered 'local' as they would in a member function, so that they can now be shared amongst multiple threads right?
Whereas if you have a member function which creates some object, this would be local to the thread and therefore it is non-shared.
Am I correct in saying this?
Consider this class
class CData
{
public:
static void func()
{
int a;
static int b;
}
int c;
static int d;
};
int main()
{
CData::func();
}
Now variable a is local to each call of func(). If two threads call func() at the same time, they get different versions of a.
b is a static local. The value persists between different calls of func(). If two threads call func() at the same time, they access the same version of b so they might need to do synchronisation.
c is an instance variable; it is attached to a particular instantiation of CData. func() cannot access c, except with a trick I'll show below.
d is a static variable. There is one instance of d shared between all uses of class CData so synchronisation may be necessary. It can be used easily from the static function func().
The trick used to access instance data from a static function is to pass a valid object into the function.
e.g.
class CData
{
public:
static void func(CData *p)
{
int a;
static int b;
b = p->c;
}
int c;
static int d;
};
int main()
{
CData data;
CData::func(&data);
}
Hope that helps.
No you are not correct.
Objects created in a static function are not shared, and this is also the case for any normal functions.
Objects can be shared though if they are declared static themselves, and it does not depends if the function is static or not.
void myFunc()
{
static MyObject o;
o.CallMethod(); // here o is shared by all threads calling myFunc
}
When an object is declared static, it is as if the object was a global variable, but only visible in the scope of the function that it is declared into.
No you are not correct. And yes, C++ does very much overuse the word "static".
A static class member variable is of course a global with the class acting as a namespace scope and with some access privilege differences if it is private or protected (can only be accessed by the class).
However a static class member function is just like a regular free-function (not class member) and has its own local variables every time it is called.
The only real difference between a static class member function and a regular free-function, apart from its naming convention, is that it has access to private members of a class (and needs an external "instance" of one).
In addition a static class member function can be called from a template with a variable template parameter, invoking what is commonly called "compile-time polymorphism" and is commonly used in meta-programming.
A static "local" variable in any function is a single-instance, on the other hand, is also a bit like a global and is sensitive to thread-contention issues as two threads calling the function access the same instance.
It does not matter if a function is static or not (class method). Only automatic variables can be seen as local to a function. If you have the address of those data, you may access it.
You can use e.g. thread-local storage to assign your output to a dedicated thread context.

What exactly does "static" mean when declaring "global" variables in C++?

This is an expansion of the scope of a previous question of mine.
What exactly is "static", how is it used, and what is the purpose of using "static" when dealing with C++?
Thanks.
It means that the variable is local to a translation unit (simply put, to a single source file), and cannot be accessed from outside it. This use of static is in fact deprecated in the current C++ Standard - instead you are supposed to use anonymous namespaces:
static int x = 0;
should be:
namespace {
int x = 0;
}
The keyword static has different meanings in C++, depending on the context.
When declaring a free function or a global variable it means that the function is not to be available outside of this single translation unit:
// test.cpp
static int a = 1;
static void foo() {}
If the result of compiling that translation unit is linked with a different translation unit containing symbols a and foo it will not break the One Definition Rule, as in this particular translation unit a and foo are private symbols. This use has been obsoleted by unnamed namespaces.
// test2.cpp
namespace {
static int a = 1;
static void foo() {}
}
When declaring a local variable within a function it means that the lifetime of the variable will extend from the first call to the function to the end of the program, and not only for the duration of the call:
int foo() {
static int counter = 0;
return ++counter;
}
int main() {
for ( int i = 0; i < 10; ++i ) {
std::cout << foo() << std::endl;
}
}
In the previous code, counter is initialized once when foo is called for the first time, but the variable will outlive the function and keep the value across different function calls. The previous code will print "1 2 3 4... 10". If the variable was not declared static then the output would be "1 1 1... 1".
Within a class scope, static means that the member is a member of the class, and not of a particular instance. This use is equivalent to the use in your other question: usage of that particular member is not bound to any specific object.
struct test {
int x;
static int y;
};
int test::y; // need to define it in one translation unit
int main() {
// test::x = 5; // !error cannot access a non-static member variable
// without an instance
test::y = 5; // ok
test t, other;
t.x = 10; // ok
t.y = 15; // ok, the standard allows calling a static member through
// an instance, but this is the same as test::y
}
In this case, the member x is a non-static member attribute, and as such there is a different x for each instance of the class. In the sample program t.x and other.x refer to different integers. On the other hand y is static and thus there is a single instance of test::y in the program. Even if the standard allows to call t.y and other.y both uses refer to the same variable. The same goes with member methods. If they are static they are class-level methods and can be called without an instance, while if they are non-static they are applied to a concrete instance and the a.b or a->b syntax must be used.
This use of static is similar to the use of the same keyword in Java, while the other two are not present in that language. There is one use of the keyword in Java that is not present in C++, and that is the use of static class initializers (a block of code at class level surrounded by static { ... }). In Java that block of code will be executed when the class is loaded and only once. Initialization of static member variables in C++ must be done in the initializer of the variable definition.
This stuff seems to be fairly well covered here.
But to paraphrase, there are 2 uses in C
Prevent the use of a global variable outside the scope of the file that defines it.
Allow local variables within a function to persist accross invocations of the function, as in
int getNextId()
{
static int id = 0;
return id++;
}
C++ inherits both of these, and adds two uses of its own.
static member variables: Variables that are "shared" accross all instances of a class, and can also be accesses without reference to an instance of the class. Shared seems like the wrong word, but in essence I beleive that the result is that any reference to a static member variable references the same memory location.
static methods: Methods that can be called without reference to a specific instance of the class that defines it.
Static basically means that a variable is tied to the lifetime of the program and not of any given function or class instance. When should you use it? Don't. What is the purpose? Debugging data, mostly.
Generally, in C++, if you find yourself using static data, you've done it wrong. There are times when it's appropriate, but they're very rare.
When static is used in a class in C++, it means more or less the same thing that it does in Java. For variables it means that one one instance of the variable exists for all classes and for functions, it means that the function does not implicitly access the this pointer at all.
In C and C++ when static is used for a global variable or function, then it means that the variable may only be referenced in the current C or C++ file. In other words, the compiler must not generate any relocation symbols for the variable or function.
When static is used next to a variable in a local function, it means that the variable does not go out of scope but will retain its value from function-call to function-call. The variable become effectively a global variable that can only be accessed from the given function.
Static class members are data and functions that are associated with the class itself, rather than with the objects of the class.
In the following example, class Fred has a static data member x_ and an instance data member y_. There is only one copy of Fred::x_ regardless of how many Fred objects are created (including no Fred objects), but there is one y_ per Fred object. Thus x_ is said to be associated with the class and y_ is said to be associated with an individual object of the class. Similarly class Fred has a static member function f() and an instance member function g().
class Fred {
public:
static void f() throw(); <-- 1
void g() throw(); <-- 2
protected:
static int x_; <-- 3
int y_; <-- 4
};
(1) Member function associated with the class
(2) Member function associated with an individual object of the class
(3) Data member associated with the class
(4) Data member associated with an individual object of the class
Usage:
When you want to keep tract of the number of instances of a class created you use static variable. For example in a 'Car' class each Car instance may have a unique serial number(_y in this case) and the company may want to keep track of the number of cars produced(_x in this case).