Introduction
This article describes basic concepts of C++ Storage Access Specifiers.
Storage Access Specifiers
- A storage class specifier is used to refine the declaration of a variable, a function, and parameters.
- A storage class specifier do not specify the scope but combined with scope to determine the storage duration and visibility of items.
- The storage class specifier used within the declaration determines whether:
- The object is to be stored in memory or in a register, if available
- The object has internal, external, or no linkage
- The object can be referenced throughout a program or only within the function, block, or source file where the variable is defined
- The storage duration for the object is static (storage is maintained throughout program run time) or automatic (storage is maintained only during the execution of the block where the object is defined)
- In C / C++ there are 4 different storage classes available: auto, extern, register, static, mutable
- How these specifiers affect objects depend also on the scope in which they appear.
- Storage class specifiers are keywords you can use in declarations to control storage duration and linkage.
- The linkage determines if declaration in different scopes can refer to the same object.
- Storage class specifiers tell compiler the duration and visibility of the variables or objects declared, as well as, where the variables or objects should be stored.
Static Storage Specifier
- Class members can be declared using the storage class specifier static in the class member list
- The declaration of a static data member in the member list of a class is not a definition. It must be defined outside the class declaration.
- When you declare an object of a class having a static member, the static member is not part of the class object.
01 class X {
02 static int f;
03 void inc()
04 {
05 f=f+1;
06 }
07 };
08 int main() {
09 X x1,x2;
10 x1.inc();
11 x2.inc();
12 cout << x1.f << ":" << x2.f << endl;
13 }
- Only one copy of the static member is shared by all objects of a class in a program.
- You can access a static member of a class by qualifying the class name using the :: (scope resolution) operator
01 class X {
02 public:
03 static int f;
04 void inc1()
05 {
06 f=f+1;
07 }
08 };
09 int X::f=0;
10 int main() {
11 X x1,x2;
12 x1.inc1();
13 x2.inc1();
14
15 cout << x1.f << ":" << x2.f << ":" << X::f << endl;
16 }
- Once you define a static data member, it exists even though no objects of the static data member's class exist.
01 class X {
02 public:
03 static int fx1;
04 void inc1()
05 {
06 fx1=fx1+1;
07 }
08 };
09 int X::fx1=10;
10 int main() {
11
12 cout << X::fx1 << endl;
13 }
The following command shows the symbols with extern linkage and we can find the static data member in this list.The $-g$ indicates only symbols with extern linkages are displayed.We can also see that symbol is initialized in the data section which is indicated by $\mathcal{D}$
- A static data can be initialized while defining in in namespace scope.
1 class X {
2 public:
3 static int fx1;
4 void inc1()
5 {
6 }
7 };
8 int X::fx1=1;
- A static data member can also be initialized while declaring the class only if it is also declared as
const
.
1 class X {
2 public:
3 const static int fx1=1;
4 };
5 const int X::fx1;
6 int main() {
7 }
- A static data member cannot be declared as mutable
1 class X {
2 public:
3 mutable static int fx1;
4 void inc1()
5 {
6 }
7 };
8 int X::fx1=1;
- Local Classes cannot have static data members.
1 int main() {
2 class X{
3 static int fx1;
4 };
5 int X::fx1=1;
- static data member can be of any type except void or void qualified with
const
or volatile.
1 class X{
2 public:
3 static void fx1() const;
4 X(){};
5 };
- Static data members and their initializers can access other static private and protected members of their classes
01 class X{
02 public:
03 static int f1;
04 static int f2;
05 static int f3;
06 static int f4;
07 static int f5;
08 static int f6;
09 int f7;
10 static int f(){return 100;}
11 X():f7(100){};
12 };
13 X x;
14 int X::f1=10;
15 int X::f2=X::f1;
16 int X::f3=X::f();
17 int X::f4=x.f1;
18 int X::f5=x.f();
19 int X::f6=x.f7;
Static Member function
- You cannot have static and nonstatic member functions with the same names and the same number and type of arguments.
01 class X{
02 public:
03 static int a;
04 static int inc()
05 {
06 a=a+1;
07 }
08 int inc()
09 {
10
11 }
12 X(){};
13 };
- Like static data members, you may access a static member function of a class without the object of the class
01 class X{
02 public:
03 static int a;
04 static int inc()
05 {
06 a=a+1;
07 }
08 X(){};
09 };
10 int X::a=0;
11 int main() {
12 cerr << X::inc() << endl;
13 }
- A static member function does not have a this pointer
01 class X{
02 public:
03 int b;
04 static int a;
05 static int inc()
06 {
07 a=this->b;
08 a=a+1;
09 }
10 X(){};
11 };
12 X obj;
13 int X::a=0;
14 int main() {
15 cerr << X::inc() << endl;
16 }
- A static member function can be declared with
const
, volatile type qualifiers
01 class X{
02 public:
03 int b;
04 static int a;
05 const volatile static int inc()
06 {
07 a=a+1;
08 }
09 X(){};
10 };
- A static member function cannot be declared as virtual function
01 class X{
02 public:
03 int b;
04 static int a;
05 const volatile static int inc()
06 {
07 a=a+1;
08 }
09 X(){};
10 };
- A static member function can access only the names of static members, enumerators, and nested types of the class in which it is declared
01 class X{
02 public:
03 int b;
04 static int a;
05 enum mode{a1,a2,a3};
06 static int inc()
07 {
08 return a1;
09 }
10 X(){};
11 };
- A static member function cannot access the non static members of the class or base class
class X{ public: int b; static int a; enum mode{a1,a2,a3}; static int inc() { return b;//this will give an error } X(){}; };
- Static data members of class have extern linkage, they can be accessed and duration is the lifetime of the program.
01 X(){};
02 };
03 X x2;
04 int X::a=0;
05
06 file : a2.cpp
07
08 class X{
09 public:
10 static int a;
11 static int inc();
12 };
13 X x1;
14
15 int b()
16 {
17 x1.a=100;
18 return x1.a;
19 }
This can be used for class members that are required to be used in all the files and its value retained across all the files, for example logging class,monitoring class etc.
- If a class object is defined as static,then this serves as a static storage access specifier,which defines the scope of the item to be file scope, duration is program execution and linkage is internal linkage.
01 ;
02
03 static X x1;
04
05 int b()
06 {
07 x1.x=100;
08 return x1.x;
09 }
10
11 file :a2.cpp
12 extern int b();
13 class X{
14 public:
15 int x;
16 };
17
18 static X x1;
19 int main()
20 {
21 x1.x=101;
22 int ff=b();
23 cerr << x1.x << ":" << ff << endl;
24
25 }