C++. Классы. Виды функций-членов класса. Простые функции-члены. Статические (static) функции-члены. Примеры использования

C++. Классы. Виды функций-членов класса. Обычные функции-члены. Статические (static) функции-члены. Примеры использования

Данная тема базируется на использовании функций-членов класса, ориентированных на компилятор Visual C++. В реализациях компиляторов разных разработчиков могут быть существенные отличия, в особенности что касается статических функций-членов.


Содержание


1. Какие виды функций-членов можно объявлять в классах?

В классах можно объявлять следующие виды функций:

  • обычные функции-члены. Это функции, в объявлении которых не используются дополнительные ключевые слова (const, volatile, static);
  • статические функции. Это функции, объявленные с ключевым словом static;
  • константные функции. Это функции, которые объявлены с ключевым словом const;
  • функции-члены, которые возвращают непостоянный объект. Это функции, объявленные с ключевым словом volatile;
  • функции-члены с константным (const) указателем this;
  • функции-члены с непостоянным (volatile) указателем this;
  • встроенные (inline) функции-члены.


2. Пример объявления класса, содержащего обычные функции-члены

В данном примере объявлен класс CLine, описывающий линию на координатной плоскости. Линия состоит из координат точек (x1; y1), (x2; y2). Класс содержит простые функции члены, объявленные в разделе public. С помощью этих функций-членов осуществляется чтение/модификация внутренних переменных класса.

// класс, который описывает линию на координатной плоскости
class CLine
{
    int x1, y1;
    int x2, y2;

    public:
    CLine(void);
    ~CLine(void);

    // методы класса
    void SetLine(int nx1, int ny1, int nx2, int ny2);
    int GetX1(void) { return x1; }
    int GetY1(void) { return y1; }
    int GetX2(void) { return x2; }
    int GetY2(void) { return y2; }
};

// Реализация методов класса
// конструктор по умолчанию
CLine::CLine(void)
{
    x1 = y1 = 0;
    x2 = y2 = 1;
}

// деструктор
CLine::~CLine(void)
{
}

// реализация простой функции-члена класса
void CLine::SetLine(int nx1, int ny1, int nx2, int ny2)
{
    x1 = nx1;
    y1 = ny1;
    x2 = nx2;
    y2 = ny2;
}

Использование класса в другом программном коде

// объявление объекта класса CLine
CLine CL;
int t;

// вызов функций-членов класса
CL.SetLine(5, 6, 10, 20);
t = CL.GetX2(); // t = 10
t = CL.GetY1(); // t = 6

3. Пример объявления класса, содержащего статические (static) функции-члены

В данном примере объявлен класс CCircle, описывающий окружность на координатной плоскости. Класс реализует следующие внутренние члены данных и методы:

  • внутренние переменные (члены) класса x, y, r (координаты центра и радиус окружности);
  • конструктор класса CCircle(), который определяет окружность с радиусом r=1 и центром в точке (0; 0);
  • статическую функцию-член класса SetData1(), которая устанавливает значение глобальных переменных xx, yy, rr объявленных за пределами класса;
  • обычную (нестатическую) функцию-член класса SetData2(), которая изменяет значение внутренних переменных x, y, r класса;
  • обычные (нестатические) методы класса, реализующие чтение значений внутренних переменных класса x, y, r и глобальных переменных xx, yy, rr.
// класс, описывающий окружность на координатной плоскости
class CCircle
{
    // внутренние переменные класса
    int x, y; // координаты центра окружности
    int r; // радиус окружности

    public:
    // конструктор класса
    CCircle(void);

    // статический метод класса - только для глобальных переменных
    static void SetData1(int nx, int ny, int nr);

    // обычные (нестатические) методы класса
    // установить новые значения внутренних переменных класса
    void SetData2(int nx, int ny, int nr);

    // взять значение внутренних переменных класса
    int GetX(void) { return x; }
    int GetY(void) { return y; }
    int GetR(void) { return r; }

    // взять значение глобальных переменных класса
    int GetXX(void);
    int GetYY(void);
    int GetRR(void);
};

// глобальные переменные
int xx, yy, rr; // эти переменные может изменять статическая функция-член класса

// конструктор класса
CCircle::CCircle(void)
{
    // заполнение значений внутренних (локальных) переменных
    x = 0; y = 0; r = 1;
}

// статическая функция-член класса
void CCircle::SetData1(int nx, int ny, int nr)
{
    // присваивание значений глобальным переменным, объявленным за пределами класса
    xx = nx;
    yy = ny;
    rr = nr;

    // работать с внутренними переменными класса в статической функции запрещено
    // x = nx; // Запрещено! Ошибка: "... illegal reference to non-static member 'CCircle::х'
    // y = ny; // тоже запрещено
}

// установить новые значения обычных (нестатических) методов класса
void CCircle::SetData2(int nx, int ny, int nr)
{
    x = nx;
    y = ny;
    r = nr;
}

// прочитать значение глобальных переменных класса
int CCircle::GetXX(void)
{
    return xx;
}

int CCircle::GetYY(void)
{
    return yy;
}

int CCircle::GetRR(void)
{
    return rr;
}

Изменять значения внутренних переменных класса с статической функции-члена класса запрещено. Если в функции SetData1() попробовать изменить значения внутренних переменных класса x, y

void CCircle::SetData1(int nx, int ny, int nr)
{
    ...
    x = nx;
    y = ny;
    ...
}

то компилятор выдаст ошибку

... illegal reference to non-static member 'CCircle::x'

Если нужно изменить значения внутренних переменных класса в статической функции, тогда этой функции нужно передать указатель this класса.

Нижеследующий программный код демонстрирует использование статической функции-члена для класса Circle

// использование класса CCircle
CCircle C1;
int tx, ty, tr; // дополнительные переменные

// вызов статической функции-члена
C1.SetData1(2, 3, 4); // изменяются только глобальные переменные xx, yy, rr
// прочитать значение внутренних переменных класса
tx = C1.Get(); // tx = 0 - внутренние переменные x,y,r инициализированы конструктором класса
tr = C1.Get(); // tr = 1

// прочитать значение глобальных переменных, объявленных за пределами класса
tx = C1.GetXX(); // tx = 2
ty = C1.GetYY(); // ty = 3

// вызов обычной (нестатической) функции-члена класса
C1.SetData2(2, 3, 4); // изменяются только внутренние переменные x, y, r
tx = C1.GetX(); // tx = 2
tr = C1.GetR(); // tr = 4

// другой способ вызова статической функции-члена
CCircle::SetData1(7, 8, 9);
tx = C1.GetXX(); // tx = 7
ty = C1.GetYY(); // ty = 8

4. Какое отличие статических функций-членов от обычных функций-членов

Основные отличия статических функций-членов от обычных:

  • вызвать статическую функцию-член можно без ссылки на объект класса, например CMyClass::MyStaticFuntion(…). В этом случае используется оператор расширения области видимости ‘::’;
  • статические функции-члены не получают указателя this класса. Это значит, что они не могут получить доступ к внутренним членам данных класса. Исключением есть статические члены-данные класса, которые объявлены с ключевым словом static;
  • в C++ статическая функция-член класса есть глобальной. Поэтому ее целесообразно использовать для изменения значений глобальных переменных, которые объявлены за пределами класса но имеют применение в классе.

5. В каких случаях целесообразно применять статические (static) функции-члены класса

Статические функции-члены класса целесообразно применять в случаях, когда в классе нужно использовать глобальные переменные, которые есть общими для разных объектов (экземпляров) этого класса.


Связанные темы