Static Member Function and Variable

Static Member Function and Variable

In this blog post, you will learn the static member function and its uses in C++ programming. Including the static member function, we also discuss the static member data (static member variable).

But before starting this blog post let’s first understand the requirement of static member function and variable in C++. It will help you in understanding static members.

So let’s discuss the requirement, during the programming sometimes we want to share a block memory with all objects.

This requirement accomplishes using the global variable but you know that the global variable is not much safer its value can be modified by anyone in the program. Personally, I don’t like the global variable.

So Now question is that if we don’t want to use global variables then how we can solve this problem?

Don’t worry C++ has a solution to this problem. The name of the solution is “static members”. Classes can contain static member data and static member functions. If you qualified a member with a static specifier, then only one copy of the member is maintained for all objects of the class.

The static members of the class are not bound to class instances. It is the reason; it is not necessary to use the class member access syntax to refer to a static member. A static member var of class Test also referred to using the qualified-id expression Test::var.

struct Test
{
    static const int var = 10;
};


int main()
{
    cout << Test::var;
   
    return 0;
}

 

Static data member:

A static data member is a data member of a class that is declared using a static specifier.  Consider the below example,

class X
{
    //data is static member variable
    static int data;
};

 

Important points related to static data members:

The following are some important points related to static data members.

1.Static members of the class are not bound to class instances.

2.Static members obey the usual class member access rules. So private access to static data members is allowed only for class-member functions and friends

3.Static member variable can be referred to using the qualified-id expression Class_Name::Attribute_Name.

4. A static data member is not part of the objects of a class. As a result, the declaration of a static data member is not considered a definition.  See the below example,

#include "iostream"
using namespace std;


class X
{
public:
    static int data;
};


int main()
{
    cout << X::data;

    return 0;
}

Output:

static member data in cpp Aticleworld

You can see we are getting a linker error.

I believe you are thinking that why the linker error is coming and how we can resolve it.

I am deciding your answer in two categories first why linker error is coming and second how we can resolve it.

So the answer to your first question is that the declaration of a non-inline static data member in its class definition is not a definition. It is the reason the linker is unable to find the definition of “data” and throws the error.

Now the answer to your second question is that you can resolve the linker error by defining the static member variable.  The syntax is following,

int X::data = 10; // definition

The static keyword is only used with the declaration of a static member but not with its definition.

 

5. Once the static data member has been defined, it exists even if no objects of its class have been created.

#include "iostream"
using namespace std;


class X
{
public:
    static int data;
};

int X::data =10;

int main()
{
    //data exist without the object
    cout << X::data;

    return 0;
}

Output: 10

 

6. We can not use mutable keywords with a static data member.

7.If a static data member is not declared thread_local there is one copy of the data member that is shared by all the objects of the class. The following example illustrates this:

#include "iostream"
using namespace std;


class X
{
public:
    static int data;
};

int X::data =10;

int main()
{
    X obj1, obj2;

    //display value of data using obj1
    cout << obj1.data<<endl;

    //change value data using obj1
    obj1.data = 12;

    //display value of data using obj2
    cout << obj2.data;

    return 0;
}

Output: 10 12

 

8. If a static data member is declared thread_local there is one copy of the member per thread.

9. If a non-volatile non-inline const static data member is of integral or enumeration type, then it can be initialized with an initializer in which every expression is a constant expression.

class Y
{
public:
    const static int a = 1;
    const static int b{2}; // since C++11
    const static int c;
};
const int Y::c = 3;

 

10.The inline and static keywords can use together for a data member. An inline static data member can be defined in the class definition and may specify an initializer. It does not need an out-of-class definition (C++17).

class Y
{
public:
    //inline with static
    inline static int n = 10;
};

 

11. There should be one definition for a static data member in C++.

 

Some real-life examples of static data members:

Example 1:

The best use of static data members is with constant macros. Let’s understand it with an example.

#include <iostream>
using namespace std;


class Y
{
public:
    const int length = 10;
};


int main()
{
    Y obj1, obj2;

    //display value of length using obj1
    cout << obj1.length<<endl;

    //display value of length using obj2
    cout << obj2.length;

    return 0;
}

 

The above class Y has a constant integral attribute “length”. The value of the length will be the same for each attribute and it will not change by any object.

example static member data cpp

The issue with the “length” attribute is that it consumes the memory for each object. I believe it is unnecessary and it becomes worse if the class has multiple objects and its uses by the less memory MCU.

We can resolve the memory wastage issue with the static keyword. It allows the creation of only a single copy of the “length” data member.

#include <iostream>
using namespace std;


class Y
{
public:
    static const int length = 10;
};


int main()
{
    Y obj1, obj2;

    //display value of length using obj1
    cout << obj1.length<<endl;

    //display value of length using obj2
    cout << obj2.length;

    return 0;
}

 

static data member in class example

 

Some valid data members of C++:

class ExampleClass
{
    static int Expirydate;  // No error

    enum Ecolor {Mango = 0, Aplle, red};   // No error

    int Data; // No error

    //error only const static member initialized in class
    static int Year = 1991;

    const static int value = 12; // No error

    const static int Sec =60; // No error

    //inline with static
    inline static int n = 10; //c++17

};
int ExampleClass::Expirydate = 918;

 

Static member function:

Like the static data member, we can also create static member functions. Consider the below example,

class X
{
public:
    //foo is static member function
    static void foo()
    {
        std::cout<<"I am static member function";
    }
};

 

Important points related to static member functions:

The following are some important points related to static member functions.

1.Static member functions of the class are not bound to class instances.

2.Static member functions obey the usual class member access rules. So private access to a static member function is allowed only for class-member functions and friends.

3.Static member functions can be referred to using the qualified-id expression Class_Name::Static_Member_Function_Name. It means static member functions are not associated with any object.

#include<iostream>

class X
{
public:
    //foo is static member function
    static void foo()
    {
        std::cout<<"I am static member function";
    }
};

int main()
{
    //function calling without object
    X::foo();
    
    return 0;
}

Output:

I am static member function

 

4.A static member function does not have this pointer. Now you are thinking why; the reason is very simple static member functions are not associated with any object, so they don’t have this pointer. The following example illustrates this:

#include<iostream>

class X
{
    const static int data = 10;
public:
    //foo is static member function
    static void foo()
    {
        //Use this pointer;
        std::cout<<this->data;
    }
};


int main()
{
    //function calling without object
    X::foo();

    return 0;
}

Output: error: ‘this’ is unavailable for static member functions.

 

5.A static member function cannot be qualified with const, volatile, virtual, or ref-qualified. Consider the below example,

static member functions

 

6.You cannot overload a static and non-static member function that has the same name and the same parameter types. The following example illustrates the same.

#include<iostream>

class X
{
public:
    //foo is static member function
    static void foo()
    {
        std::cout<<"I am static member function";
    }

    void foo()
    {
        std::cout<<"I am non-static member function";
    }
};

int main()
{

    return 0;
}

Output: error: ‘void X::foo()’ cannot be overloaded

 

7.The address of a static member function may be stored in a regular pointer to function, but not in a pointer to member function. The following example illustrates the same.

Example-1:

Pointer to member function with non-static member function.

#include<iostream>

struct X
{
    void foo()
    {
        std::cout << "I am non-static member function\n";
    }
};

int main()
{
    // pointer to member function foo of class X
    void (X::* fptr)() = &X::foo;

    //object of X
    X obj;

    //calling member function
    (obj.*fptr)();

    return 0;
}

Output: I am non-static member function

 

Example-2:

Pointer to member function with static member function.

#include<iostream>

struct X
{
    //static member function
    static void foo()
    {
        std::cout << "I am non-static member function\n";
    }
};

int main()
{
    // pointer to member function foo of class X
    void (X::* fptr)() = &X::foo;

    //object of X
    X obj;

    //calling member function
    (obj.*fptr)();

    return 0;
}

Output: error: cannot convert ‘void (*)()’ to ‘void (X::*)()’ in initialization

 

Note: The type of “pointer-to-member-function” is different from “pointer-to-function”.

 

Use of static member function in C++:

There are many uses of static member functions but here we will discuss a few of them.

Accessing private static data member:

The static data member can be accessed without creating the instance but as you know that it obeys the class rule. The private static data member is only accessed by the class-member functions and friends.

If you will try to access the private static member function, you will get the compiler error. The following example illustrates the same.

#include<iostream>

class X
{
    //private static member
    static int t;
};

int X::t = 3;

int main()
{
    X::t;

    return 0;
}

Output: error: ‘int X::t’ is private

 

The above code is throwing the error because we breaking the class rule. We can easily solve this problem using the static member function

#include<iostream>

class X
{
    static int t;
public:
    //static member function
    static void foo()
    {
        std::cout << t <<std::endl;
    }
};

int X::t = 3;

int main()
{
    X::foo();

    return 0;
}

Output: 3

 

Meta-programming:

The static member functions are very good for template meta-programming. The template std::char_traits is a very good example. All member functions are static.

 

Click to solve Quiz on static members.

 

Recommended Articles for you: