static keyword inside a class and outside it - c++

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.

Related

C++ static class member with private constructor

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. :)

Definition of the static data member

I'm reading Scott Meyers' C++ and come across this example:
class GamePlayer{
private:
static const int NumTurns = 5;
int scores[NumTurns];
// ...
};
What you see above is a declaration for NumTurns, not a definition.
Why not a definition? It looks like we initialize the static data member with 5.
I just don't understand what it means to declare but not define a variable with the value 5. We can take the address of the variable fine.
class A
{
public:
void foo(){ const int * p = &a; }
private:
static const int a = 1;
};
int main ()
{
A a;
a.foo();
}
DEMO
Because it isn't a definition. Static data members must be defined outside the class definition.
[class.static.data] / 2
The declaration of a static data member in its class definition is not
a definition and may be of an incomplete type other than cv-qualified
void. The definition for a static data member shall appear in a
namespace scope enclosing the member’s class definition.
As for taking the address of your static member without actually defining it, it will compile, but it shouldn't link.
you need to put a definition of NumTurns in source file, like
const int GamePlayer::NumTurns;

C++ lambda friendship

When a lambda function is declared inside a function F which is a friend of class C, does the lambda function have access to C private members? Specifically, does the standard allow it?
C++11 §[expr.prim.lambda] 5.1.2/3:
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type — whose properties are described below. This class type is not an aggregate (8.5.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. ...
Since the closure type is declared within the friend function, it will have the same access per §[class.local] 9.8/1:
A class can be declared within a function definition; such a class is called a local class. The name of a local class is local to its enclosing scope. The local class is in the scope of the enclosing scope, and has the same access to names outside the function as does the enclosing function. ...
A nested class automatically has access to all the members its "owner" has access to. You don't need lambdas to see this:
class A {
friend struct B;
friend void g();
static void f() { }
};
struct B {
struct C {
static void f() { A::f(); }
};
static void f() { C::f(); }
};
void g() {
struct D {
static void f() { A::f(); }
};
D::f();
}
Despite not being listed explicitly as friends, C::f and D::f can call the private A::f without any complaints from the compiler.
Lambdas are implemented using compiler-generated local classes (that's not just an implementation detail, that's what the standard requires), so the same rules as for other local classes apply.
The rule that local classes can access the same members is spelled out in the standard in 9.8:
The local class is in the scope of the enclosing scope, and has the same access to names outside the function as does the enclosing function.

Which function is used to initialize the static class member?

I have a question about which function is chosen to init a static class member.
//Base.h
class Base
{
private:
static int count;
static int countInit()
{
return 10;
}
public:
Base()
{
}
};
//and Base.cpp
static int countInit()
{
return 0;
}
int Base::count=countInit();//member function is used.
static int local_count=countInit();//the local one in Base.cpp
The variable Base::count is initialized with Base::countInit() rather than the countInit() defined in Base.cpp. But the local_count is initialized by the local countInit. So, I wonder, is there a rule like Koenig lookup within this case?
After you write int Base::count you are in class Base, so static function of class will be called. Unqualified lookup will be used here
from 3.4.2/13
A name used in the definition of a static data member of class X (9.4.2) (after the qualified-id of the static
member) is looked up as if the name was used in a member function of X.
from 9.4.2
The definition for a static data member 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
Example:
class process {
static process* run_chain;
static process* running;
};
process* process::running = get_main();
process* process::run_chain = running;

What restrictions does ISO C++03 place on structs defined at function scope?

We're not allowed to define a functor struct inside a function because one is not allowed to use function declared structs in the instantiation of function templates.
Are there any other significant pitfalls to be aware of? E.g. would this be bad:
int foo()
{
struct Scratch
{
int a, b, c;
};
std::vector<Scratch> workingBuffer;
//Blah Blah
}
1. C++ standard forbids using locally-defined classes with templates.
14.3.1/2: A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.
A code example:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as
// template-argument
X<S*> x4; // error: pointer to local type
// used as template-argument
}
Here is a little more reference from IBM documentation:
2. Declarations in a local class can only use type names, enumerations, static variables from the enclosing scope, as well as external variables and functions.
A Code Example:
int x; // global variable
void f() // function definition
{
static int y; // static variable y can be used by
// local class
int x; // auto variable x cannot be used by
// local class
extern int g(); // extern function g can be used by
// local class
class local // local class
{
int g() { return x; } // error, local variable x
// cannot be used by g
int h() { return y; } // valid,static variable y
int k() { return ::x; } // valid, global x
int l() { return g(); } // valid, extern function g
};
}
int main()
{
local* z; // error: the class local is not visible
return 0;
}
3. A local class cannot have static data members
A Code Example:
void f()
{
class local
{
int f(); // error, local class has noninline
// member function
int g() {return 0;} // valid, inline member function
static int a; // error, static is not allowed for
// local class
int b; // valid, nonstatic variable
};
}
The scope of the local classes is the function in which they're defined.But that isn't interesting in itself1.
What makes local classes interesting is that if they implement some interface, then you can create instances of it (using new) and return them, thereby making the implementation accessible through the base class pointer even outside the function.
Some other facts about local classes:
They cannot define static member variables.
They cannot access nonstatic "automatic" local variables of the enclosing function. But they can access the static variables.
They can be used in template functions. They cannot be used as template argument, however.
If they defined inside template function, then they can use the template parameters of the enclosing function.
Local classes are final, that means users outside the function cannot derive from local class to function. Without local classes, you'd have to add an unnamed namespace in separate translation unit.
Local classes are used to create trampoline functions usually known as thunks.
Some references from the Standard (2003)
9.8 Local class declarations [class.local]
\1. A class can be defined within a function definition; such a class is
called a local class. The name of a
local class is local to its enclosing
scope. The local class is in the scope
of the enclosing scope, and has the
same access to names outside the
function as does the enclosing
function. Declarations in a local
class can use only type names, static
variables, extern variables and
functions, and enumerators from the
enclosing scope.
[Example:
int x;
void f()
{
static int s ;
int x;
extern int g();
struct local {
int g() { return x; } // error: x is auto
int h() { return s; } // OK
int k() { return ::x; } // OK
int l() { return g(); } // OK
};
// ...
}
local* p = 0; // error: local not in scope
—end example]
\2. An enclosing function has no special access to members of the local
class; it obeys the usual access rules
(clause 11). Member functions of a
local class shall be defined within
their class definition, if they are
defined at all.
\3. If class X is a local class a nested class Y may be declared in
class X and later defined in the
definition of class X or be later
defined in the same scope as the
definition of class X. A class nested
within a local class is a local class.
\4. A local class shall not have static data members.
Local structs / classes can't have static data members, only static member functions. Also, they can't be templates.
Yes. Local classes can't be used as template parameters in C++03
local structs are perfectly legal, even in C++98. You cannot use them with templates in C++98 though, whereas you can in C++0x. g++ 4.5 supports using local structs with templates in -std=c++0x mode.