Last Updated:

Static members c++ class | Friend class in c++ 

1. Static Class Members

When you declare a class, you can declare the member data and member functions of the class static by using the static keyword. There is only one instance of static class member data that is shared by all objects of that class in the program. A static member is not a part of the objects of the class, but a separate object. A static class member will exist even if no class objects have been created.

Declaring static member data inside a class definition is not its definition. The definition should be given somewhere else.

The static mem member of the cl class can be denoted as cl::mem, i.e. independent of the object. It can also be referenced by using the . and -> class member access operations. When a static class member is accessed through a class member access operation, the expression to the left of that operation is not evaluated.

A member function of a class can also be static. Such a function does not receive a this pointer and can only reference non-static class members through class member access operations (.. and ->).

A static class member function cannot be virtual. A static and non-static class member function with the same name and set of parameters cannot exist at the same time.

Static members of the global class have external binding, i.e. can be accessed from other program files. Local (that is, declared within some function) classes cannot have static members.

Static class members obey the normal rules for accessing class members.

Constant static class members can be initialized inside a class definition.

class BitSet
 { private:
     typedef _int64 elem;
     static const int cBits = sizeof(elem) * 8;
     static const int size  = 256 / cBits;
     elem set[size];
   ...
  };

For an example of using static class members, see the example at the end of the lecture.

2. Friends of the Class

The usual declaration of a class member function guarantees three logically different things:

  1. the function has the right to access private members of the class;
  2. The function is in the scope of the class.
  3. the function must be called on the class object (there is a pointer to this).

By declaring a function static, we give it only the first two properties. By declaring a function friendly, we give it only the first property.

A class friend is a function that is not a member of that class, but that is allowed to use its private and protected members. The name of a class friend does not lie within the scope of that class, and the other class is not invoked by a class member access operation.

A class friend, like its members, is part of the class's interface. Friendship, like other access rights, is granted by the class, not captured.

Access specifiers do not affect friendly feature ads. "Friendship" has neither heritability nor transitivity.


class Complex
 { private:
    double r, m;
   public:
    Complex(double r = 0,  double m = 0) : r(r), m(m) { }
    //operator double () { return r; };
    Complex  operator =(const Complex& c);
    friend Complex  operator ++(Complex& c);
    friend Complex  operator ++(Complex& c, int);
    friend Complex operator + (const Complex& c1,  const Complex& c2);      
    Complex  operator +=(const Complex& c);
  };     the operator += function is best implemented as a member function of a class 
 Complex Complex::operator =(const Complex& c) { if (&c == this)  return *this; r = c.r; m = c.m; return *this; } Complex  operator ++(Complex& c) { ++c.r;  return c; } Complex  operator ++(Complex& c, int) { Complex x = c; c.r++; return x; } Complex  operator +(const Complex& c1,  const Complex& c2) { return Complex(c1.r + c2.r, c1.m + c2.m); } Complex Complex::operator +=(const Complex& c) { r += c.r; m += c.m; return *this;
  }

void main()
 { Complex a(0, 0), b(2, 2), c;
   double d = 2;
   
   c = ++a;
   c = a++;
   c = a + ++b;
   c = a + d;
   c = 3 + b;
   c += 4;
   2 += c;
  } 

When a shared function is declared friendly, only a function with specified parameter types becomes a friend. This is done to avoid "grabbing" access rights by declaring another shared function with a new set of parameters.

A member function of class X can be friendly to class Y.


class Y { friend void X::f(); ... };

All member functions of class X can be declared friendly to class Y at once:


class Y { friend class X; ... };

The friendliness mechanism is important for two reasons. First, a function can be a friend of two classes. This increases the efficiency of such a function and simplifies class interfaces.

Second, a friendly function allows custom transformations to be applied to its first parameter, while class member functions do not. This allows the programmer to express the requirement for the first parameter to be an l-value** by describing the corresponding function as a member of the class, and conversely, to express the absence of such a requirement by describing such a function as friendly.


class Complex
 { private:
    double r, m;
   public:
    Complex(double r = 0,  double m = 0) : r(r), m(m) { }
    //operator double () { return r; };
    Complex  operator =(const Complex& c);
    friend Complex  operator ++(Complex& c);
    friend Complex  operator ++(Complex& c, int);
    friend Complex operator + (const Complex& c1,  const Complex& c2);      
    Complex  operator +=(const Complex& c);
  };     the operator += function is best implemented as a member function of a class 
 Complex Complex::operator =(const Complex& c) { if (&c == this)  return *this; r = c.r; m = c.m; return *this; } Complex  operator ++(Complex& c) { ++c.r;  return c; } Complex  operator ++(Complex& c, int) { Complex x = c; c.r++; return x; } Complex  operator +(const Complex& c1,  const Complex& c2) { return Complex(c1.r + c2.r, c1.m + c2.m); } Complex Complex::operator +=(const Complex& c) { r += c.r; m += c.m; return *this;
  }

void main()
 { Complex a(0, 0), b(2, 2), c;
   double d = 2;
   
   c = ++a;
   c = a++;
   c = a + ++b;
   c = a + d;
   c = 3 + b;
   c += 4;
   2 += c;
  } 

 

3. Example

The example class is part of a program in which there are several moving circles on the screen. When the mouse hits the circle, it is destroyed. The program ends after all the circles are destroyed.

There are three static members in the Circle class—variables that store the total number of circles and the size of the program window. One instance of each of these variables is shared by all Circle objects. The Circle class also declares the SetSize and GetCount functions that work with static class members. Because these functions must be called regardless of any object of the class, and even when no Object of the Circle class exists, they must be declared as friendly functions or as static member functions of the class. If functions are declared as static member functions of a class, they must be qualified by the class name using a scope resolution operation when they are called.

Circle.h file

 

class Circle

{ private:

   static int count;

   static long int maxX, maxY;

   int x, y, sx, sy;

   int radius;

   int colour;

  public:

   Circle();

   ~Circle();

   friend void SetSize(int x, int y);

   friend int  GetCount();

   void Paint(HDC hdc);

   void Move();

   int  Is_Inside(int px, int py);

   int  GetColour();

   void ChangeSpeed();

 };

#define WM_END (WM_USER + 1)

The Circle file.cpp

 

#include "StdAfx.h"
#include "Circle.h"


extern HWND hWnd;

int Circle::count = 0;
long int Circle::maxX = 800;
long int Circle::maxY = 600;

Circle::Circle()
{ ++count;
  x = rand() % maxX;
  y = rand() % maxY;
  radius = rand() % 7 + 6;
  colour = rand() % 16;
  sx = rand() % 15 - 7;
  sy = rand() % 15 - 7;
 }

Circle::~Circle()
{ if (--count == 0)
   PostMessage(hWnd, WM_END, 0, 0);
 }
   
void Circle::Paint(HDC hdc)
{ Ellipse(hdc, x - radius, y + radius, x + radius, y - radius); }

void Circle::Move()
{ x += sx;
  if (x < 0) x = 0;
  if (x > maxX) x = maxX;
  y += sy; 
  if (y < 0) y = 0;
  if (y > maxY) y = maxY;
 }

int  Circle::Is_Inside(int px, int py)
{ return (px - x) * (px - x) + (py - y) * (py - y) <= radius * radius ;}

void SetSize(int x, int y)
{ Circle::maxX = x; Circle::maxY = y; }

int  Circle::GetColour()
{ return colour; }

int GetCount()
{ return Circle::count; }

void Circle::ChangeSpeed()
{ sx = rand() % 15 - 7; sy = rand() % 15 - 7; }