this code compiles and runs without errors:
class foo{
static foo *ref;
foo(){}
public:
static foo *getRef(){
return ref;
}
void bar(){}
};
foo* foo::ref = new foo; // the construcrtor is private!
int main(int argc, const char *argv[])
{
foo* f = foo::getRef();
f->bar();
return 0;
}
could somebody explain why can the constructor be called?
That scope isn't global - static members are at class scope, and so their initialization expression is also at class scope.
The answer is that it is not available in the global scope. The initializer of a static member is defined to be inside the class scope, so it has access to the private members.
§9.4.2/2 [...]The initializer expression in the definition of a static data member is in the scope of its class (3.3.6).
This form of initialization of static members are not necessary in older c++. They are made compulsary in later release of c++.
And, this form of static member initialization will generally used to initialize the static members before creation of any class objects.
(E.g) int MyClass::objectsCounter=0;
But by,
foo* foo::ref = new foo;
this statement you are just initializing a static member (which is of pointer type) by creating a new object.
And in this case you are intializing a private member by calling a private method of its own class.
Hence there is no role of globe scope here.
Related
Why can a private constructor be used in this case? I can't explain it to myself. In this case, I initialize the class field (the type of which is the same class) from the outside, since it is static.
Edit1:
I use C++ 17 (gcc 11.2).
#include <iostream>
using namespace std;
class MainMenu {
public:
MainMenu(const MainMenu& other) = delete;
MainMenu& operator=(const MainMenu& other) = delete;
static MainMenu& GetInstance() { return _instance; }
private:
static MainMenu _instance;
MainMenu() { cout << __PRETTY_FUNCTION__ << endl;}
};
// HERE HERE HERE!!
MainMenu MainMenu::_instance = MainMenu(); // Or just MainMenu MainMenu::_instance;
int main() {
MainMenu::GetInstance();
return 0;
}
Result:
MainMenu::MainMenu()
Process finished with exit code 0
I would use the following mental model for it:
a. Note that your are instantiating the variable (it would have an incomplete type at the class's scope, so it cannot be inline withing the class's scope), not actually (re)assigning it
b. it is already declared global/static on class's scope so technically the constructor is called within the class. That's fine, even with the constructor being private, because it's called from exactly that privately accessible scope. True, the definition outside looks off, but that does not matter, as the declaration specifies its scope.
Excerpt from C++17 standard:
12.2.3.2 Static data members [class.static.data]
2 The declaration of a non-inline static data member in its class definition is not a
definition and may be of an incomplete type other than cv void. The
definition for a static data member that is not defined inline in the
class definition shall appear in a namespace scope enclosing the
member’s class definition. In the definition at namespace scope, the
name of the static data member shall be qualified by its class name
using the :: operator. The initializer expression in the definition of
a static data member is in the scope of its class (6.3.7)
And the example is your case exactly:
class process {
static process* run_chain;
static process* running;
};
process* process::running = get_main();
process* process::run_chain = running;
Any additional citations from the C++ standard to explain it in a better way are most welcome. :)
So I understand that:
class Foo {
public:
static int bar;
}
Means I can access Foo::bar more or less anywhere.
But what about code like this?
class Foo {
public:
static int* bar() {
static int fred = 1;
static int barney = 2;
static int thelma = 3;
return &thelma;
}
};
How do I access fred and barney? I understand they are created only once and they exist for the lifetime of the program but presumably they aren't accessible as Foo::barney.
I have seen this pattern in real code and so wondering how it works.
There are two important concept in C++: visibility and lifetime of variables.
How do I access fred and barney? I understand they are created only once and they exist for the lifetime of the program but presumably they aren't accessible as Foo::barney.
You can't access them (not at least via their name as compiler won't be able to link them as they have no-linkage). Static variables inside your member function has visibility only inside the function; lifetime of the program (to be precise, it begins the first time the program flow encounters the declaration and it ends at program termination) and internal linkage.
static variable are used in singleton design pattern. Since, they have limited visibility but program's lifetime, that's how you can access a static variable outside the member function.
class A {
public:
A& getInstance()
{
static A self;
return self;
}
A(const A&) = delete;
A& operator=(const A&) = delete;
private:
A();
};
As reported in this Q&A, const static member functions are/were not available in C++. Did anything change since then (2011)?
Is there another way to have static member functions that do not modify the static members of their class?
Something like (pseudo-code):
class C
{
static int a;
public:
static void Incr() { ++a; }
static int Ret() const { return a; }
};
int C::a = 0;
I would need to call a [const] static member function from another class' const member function.
According to the current cppreference.com (page about static members), static member functions still cannot be const, because the const keyword only modifies the this pointer, which static functions obviously do not have.
So nothing seems to have changed since the answer you were referring to was written.
Did anything change since then (2011)?
Nothing changed, you still can't cv-qualify a static member function.
Is there another way to have static member functions that do not modify the static members of their class?
Not a perfect solution, but you may declare const "aliases" to static data members:
static int Ret() {
static constexpr const auto& a = C::a;
// Now C::a is shadowed by the local a
// and the function can't modify it.
// a = 2; // ill-formed
return a * 2; // OK
}
It still requires discipline, but at least that way a compiler can catch unintended modification attempts.
Class which has only static fields and static methods doesn't deserve to be called class. It is just form of functions and global variables with fancy name spacing.
Anyway IMO it is much better to have a regular class with regular fields and methods and then instantiate it as a global variable (not very nice solution, but at least more honest where class contains only static fields and methods).
class C
{
int a;
public:
C() : a(0) {}
void Incr() { ++a; }
int Ret() const { return a; }
};
C instance;
Or use singleton pattern which I hate.
From generated code perspective there should be no difference.
The static keyword is related to internal linkage generally, but the static keyword used inside a class has external linkage right? The variables m, n below are accessible outside the class file.
class c {
int i;
int j;
static int m;
static int n;
public:
void zap();
static void clear();
};
Right.
The keyword static is heavily overloaded with too many different meanings:
On a variable or function at namespace scope it gives the name internal linkage.
On a class member it makes it a static member, which doesn't affect linkage.
On a variable at function scope it gives the variable "static storage duration" as opposed to "automatic" or "dynamic" storage duration (i.e. the variable's lifetime extends to the end of the program, like global variables.)
As I stated in my comment, static members are those associated only with the class rather than individual objects.
static members belong to the class; for variables, they're accessible without an object and shared amongst instances e.g.
struct Foo {
static void *bar;
static void *fu();
}
so Foo::bar and Foo::fu are legal.
They are introduced in §9.4 of the C++03 standard;
A data or function member of a class may be declared static in a class definition, in which case it is a static member of the class.
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
class process {
public:
static void reschedule();
};
process& g();
void f()
{
process::reschedule(); // OK: no object necessary
g().reschedule(); // g() is called
}
A static member may be referred to directly in the scope of its class or in the scope of a class derived (clause 10) from its class; in this case, the static member is referred to as if a qualified-id expression was used, with the nested-name-specifier of the qualified-id naming the class scope from which the static member is referenced.
int g();
struct X {
static int g();
};
struct Y : X {
static int i;
};
int Y::i = g(); // equivalent to Y::g();
...
You could say that static members are members of the class and not any specific object instance. That is, they have the same value for all object instances.
Static member functions, while not having a value, are otherwise the same. Instead of being unique for each object instance, they can be seen as part of the class. This means that they have no this pointer and can not access non-static member variables.
static function in c++
SO, there can be only one instance of static function for this class. Right?
In C++, a static member function is just like a normal, global function, except with respect to visibility of names:
The name of the function is qualified with the class name.
Like a friend function, a static member function has access to private and protected class members. Also like a friend function, however, it does not have a this pointer, so it only has access to those parts of objects to which you've given it access (e.g., passed as a parameter).
(Thanks Alf): You can't declare any member function (static or otherwise) as extern "C".
A static member function (inside a class) means that you can call that function without creating an instance of the class first. This also means that the function cannot access any non-static data members (since there is no instance to grab the data from).
e.g.
class TestClass
{
public:
TestClass() {memberX_ = 10;}
~TestClass();
// This function can use staticX_ but not memberX_
static void staticFunction();
// This function can use both staticX_ and memberX_
void memberFunction();
private:
int memberX_;
static int staticX_;
};
Making a function static allows it to be called without instantiating an instance of the class it belongs to. learncpp.com has some more on the subject and check out the following example which will fail to compile:
class Foo
{
public:
static void Bar1();
void Bar2();
};
int main(int argc, char* argv[])
{
Foo::Bar1();
Foo x;
x.Bar2();
Foo::Bar2(); // <-- error C2352: 'Foo::Bar2' : illegal call of non-static member function
return 0;
}
Static functions can be called without actually creating a variable of that type, e.g.:
class Foo
{
public:
static void Bar();
void SNAFU();
};
int main( void )
{
Foo::Bar(); /* Not necessary to create an instance of Foo in order to use Bar. */
Foo x;
x.SNAFU(); /* Necessary to create an instance of Foo in order to use SNAFU. */
}