§ 22. Тып даных клас (class)

22.2. Апісанне класа

У класе аб’яўляюцца даныя і функцыі, якія аперыруюць гэтымі данымі (выконваюць іх апрацоўку).

Кожная пераменная тыпу «клас» з’яўляецца аб’ектам. Аб’ект класа вызначаецца пэўным значэннем даных (пераменных), якое называюць станам аб’екта.

Даныя, якімі можна характарызаваць аб’ект класа, называюць палямі. Функцыі, што могуць выконваць якія-небудзь дзеянні над данымі (уласцівасцямі) класа, называюць метадамі.

У C++ класы вельмі падобныя да структур, але забяспечваюць значна большую магутнасць і гнуткасць.

Для вызначэння такога тыпу даных у C++ выкарыстоўваецца ключавое слова class. У прыкладзе 22.1 прыведзены апісанні класаў (некаторыя з прыкладаў выкарыстоўваліся для апісання структур). У прыкладзе 22.2 дадзена апісанне аб’ектаў адпаведных класаў.

Усе ўласцівасці і метады класаў маюць правы доступу. Па змоўчанні ўсё змесціва класа зяўляецца даступным для чытання і запісу толькі для яго самога. Для таго каб дазволіць доступ да даных класа звонку, выкарыстоўваюць мадыфікатар доступу public. Усе функцыі і пераменныя, якія знаходзяцца пасля мадыфікатара public, становяцца даступнымі з усіх частак праграмы.

Закрытыя даныя класа змяшчаюцца пасля мадыфікатара доступу private. Калі адсутнічае мадыфікатар public, то ўсе функцыі і пераменныя па змоўчанні з’яўляюцца закрытымі.

Звычайна прыватнымі робяць усе ўласцівасці класа, а публічнымі — яго метады. Усе дзеянні з закрытымі ўласцівасцямі класа рэалізуюцца праз яго метады.

У агульным выглядзе апісанне класа выглядае наступным чынам:

class імя_класа
{
  private:
  /* спіс уласцівасцей і метадаў для   
  выкарыстання ўнутры класа
 */
  public:
  /* спіс метадаў, даступных іншым функцыям 
  і аб’ектам праграмы
 */
  protected:
  /*спіс сродкаў, даступных для   
  дружалюбных класаў і наследнікаў
*/
};

Паколькі метад у класе з’яўляецца функцыяй, то і апісваюць метады гэтак жа, як апісваюць функцыі.

Аб’яўляюць метады ўнутры класа, а вызначэнне метадаў можа быць як унутры класа, так і па-за ім. Вызначэнне метадаў па-за класам дазваляе пры неабходнасці лёгка вынесці іх у асобны файл. У прамысловай распрацоўцы ПЗ паступаюць менавіта такім чынам.

Вызначэнні метадаў класа вельмі падобны да звычайных вызначэнняў функцый. Кожны з метадаў мае загаловак і цела, можа мець тып значэння, якое вяртаецца, і параметры. Але ёсць і адрозненні:

  1. 1. Пры вызначэнні функцыі як метаду класа выкарыстоўваецца значок «::»[2] для ідэнтыфікацыі класа, якому належыць функцыя.
  2. Метады класа маюць доступ да ўсіх прыватных кампанентаў свайго класа.

У прыкладзе 22.3 прыведзены апісанні класаў з прыкладу 22.1, дапоўненыя апісаннем метадаў.

Паколькі даныя ў класе з’яўляюцца прыватнымі, карыстальнік не можа напрамую вызначыць ці змяніць значэнні даных. Для гэтых мэт выкарыстоўваюцца спецыяльныя метады.

У класах прынята аб’яўляць так званыя set- і get-функцыі (у рускамоўнай літаратуры іх часам называюць сетары і гетары), з дапамогай якіх можна працаваць з элементамі даных. Такіх функцый у класе можа быць некалькі.

У прыкладзе 22.4 паказана, як можна ўстанавіць set- і get-функцыі для класа date. Функцыі-сетары дазваляюць устанавіць дзень, месяц ці год у даце. Функцыя-гетар дазваляе атрымаць частку даты (дзень і месяц) у выглядзе радка, у якім дзень і месяц падзелены кропкай.

Для пачатковай ініцыялізацыі класа выкарыстоўваюцца канструктары. Канструктар —  спецыяльны тып метаду класа, які аўтаматычна выклікаецца пры стварэнні аб’екта гэтага ж класа. Канструктары звычайна выкарыстоўваюцца для ініцыялізацыі ўласцівасцей аб’екта класа.

У адрозненне ад звычайных метадаў канструктары маюць пэўныя правілы называння:

  • канструктар павінен мець тое ж імя, што і клас;
  • канструктар не мае тыпу вяртання.

У класе можа быць некалькі канструктараў. Канструктар, які не мае параметраў, называецца канструктарам па змоўчанні. Ён выклікаецца, калі карыстальнікам не паказаны значэнні для ініцыялізацыі. Канструктары таксама могуць быць абвешчаны з параметрамі, якія выкарыстоўваюцца для ініцыялізацыі палёў. У класе можна вызначыць любую колькасць канструктараў, кожны з якіх павінен мець унікальныя параметры.

У прыкладзе 22.5 у клас date дабаўлены тры канструктары. Канструктар па змоўчанні, які ўстанаўлівае дату 01.01.1900; канструктар, які прымае тры параметры — дзень, месяц, год; канструктар з адным параметрам — радком, які змяшчае дату, з раздзяляльнікам «.».

Канструктары, як і set- і get-функцыі, звычайна аб’яўляюцца публічнымі.

В прыкладзе 22.5 прадэманстравана работа з класам у функцыі main.

Дэструктар класа — яшчэ адзін спецыяльны метад — выклікаецца пры знішчэнні аб’екта. Імя дэструктара аналагічна імені канструктара, толькі ў пачатку ставіцца знак тыльды: ~. Дэструктар не мае ўваходных параметраў. Дэструктар заўсёды адзін. Для простых класаў (тых, якія толькі ініцыялізуюць значэнні звычайных уласцівасцей) дэструктар не патрэбны, бо C++ аўтаматычна выканае ачыстку памяці самастойна. Дэструктары не выклікаюцца яўна. Аднак іх могуць бяспечна выклікаць іншыя метады класа, паколькі аб’ект не знішчыцца да таго часу, пакуль не выканаецца дэструктар.


[2] Значок абазначае аперацыю «раскрыццё вобласці бачнасці».

Складаныя тыпы даных (радок, вектар, спіс, стэк і інш.) з STL рэалізаваны як класы. Таму, калі вы апісваеце зменную любога з гэтых тыпаў, вы ствараеце аб’ект класа. А калі вы выклікаеце функцыю з выкарыстаннем гэтых аб’ектаў, вы выклікаеце метад.

Прыклад 22.1. Апісанне класаў.

Клас для апісання пункта на плоскасці:

class tchk
{
  double x, y;
};

Клас для апісання даты:

class date
{
  int d, m, g;
};

Клас, які апісвае студэнта, што паступіў у ВНУ па выніках ЦТ:

class student

{

  string fam, gorod;

  int god_r;

  vector <int> otm = vector<int>(3);

  int sr_bal;

};

У дадзеным прыкладзе для кожнага студэнта захоўваецца яго прозвішча (fam), горад, з якога ён прыехаў (gorod), год нараджэння (god_r). У вектары otm[1] захоўваюцца тры адзнакі, атрыманыя на ЦТ, поле sr_bal прызначана для захоўвання сярэдняга бала атэстата.

Прыклад 22.2. Апісанне пераменных тыпу клас.

tchk A, B;
date d1, d2;
vector <student> gruppa (30);

Тут апісаны пераменныя А і В тыпу tchk (два пункты); пераменныя d1 і d2 тыпу date (дзве даты) і пераменная gruppa, што з’яўляецца масівам, які змяшчае апісанне для 30 студэнтаў.

Галоўным адрозненнем у апісанні структуры і класа з’яўляецца тое, што пры апісанні структуры па змоўчанні ўсе палі і функцыі з’яўляюцца публічнымі, але пры неабходнасці іх можна зрабіць прыватнымі. У класе па змоўчанні ўсе ўласцівасці і метады з’яўляюцца прыватнымі, а публічнымі іх робяць пры неабходнасці.

Прыклад 22.3 Пашырэнне апісання класаў.

Клас для апісання пункта на плоскасці. Дабаўлены метад вылічэння вугла нахілу да восі OX адрэзка, які злучае пачатак каардынат з пунктам.

class tchk

{

  private:

    double x, y;

  public:

    double ugol();

};

 

double tchk::ugol()

{

  double tg = y / x;

  return atan(tg) * 180 / acos(-1);

}

Класс для апісання даты. Дабаўлены метад для вываду даты на экран з раздзяляльнікам «.»:

class date

{

  private:

   int d, m, g;

  public:

   void print();

};

 

void date::print()

{

  cout << d << "." << m << "." << g;

}

Клас, што апісвае студэнта, які паступіў у ВНУ па выніках ЦТ. Дабаўлены метад для вылічэння сумарнага бала адзнак:

class student

{

  private:

    string fam, gorod;

    int god_r;

    vector <int> otm = vector<int>(3);

    int sr_ball;

  public:

    int summ();

};

 

int student::summ()

{

   int s = 0;

   for (auto i:otm)

     s += i;

   return s;

}

Прыклад 22.4 Дабаўленне set- і get- функцый да класа date.

class date

{

  private:

    int d, m, g;

  public:

    void print();

    void set_den(int x) {= x;}

    void set_mesjac(int x) {= x;}

    void set_god(int x) {= x;}

    string get_date_dm();

};

 

void date::print()

{

  cout << d << "." << m << "." << g;

}

 

string date::get_date_dm()

{

  string t1 = to_string(d);

  string t2 = to_string(m);

  return t1 + "." + t2;

}

Прыклад 22.5 Дабаўленне канструктараў да класа date. Дэманстрацыя работы з класам.

Праграма:

#include <iostream>

#include <vector>

#include <cmath>

#include <string>

 

using namespace std;

using namespace std::__cxx11;

 

class date

{

  private:

    int d, m, g;

  public:

    date() {= 1; m = 1; g = 1900;}

    date(int t_d, int t_m, int t_g);

    date(string s);

    void print();

    void set_den(int x) {= x;}

    void set_mesjac(int x) {= x;}

    void set_god(int x) {= x;}

    string get_date_dm();

};

 

date::date(int t_d, int t_m, int t_g)

{

  d = t_d;

  m = t_m;

  g = t_g;

}

 

date::date(string s)

{

  d = stoi(s.substr(0,2));

  m = stoi(s.substr(3,2));

  g = stoi(s.substr(6,4));

}

 

void date::print()

{

  cout << d << "." << m << "." << g;

}

 

string date::get_date_dm()

{

  string t1 = to_string(d);

  string t2 = to_string(m);

  return t1 + "." + t2;

}

 

int main()

{

  date d1;

  d1.print();

  cout << endl;

  cout << "tri chisla" << endl;

  int t1, t2, t3;

  cin >> t1 >> t2 >> t3;

  date d2(t1, t2, t3);

  d2.print();

  cout << endl;

  string s = "13.07.2020";

  date d3(s);

  cout << d3.get_date_dm() << endl;

  return 0;

}

Тэсціраванне.

Аналіз вынікаў.

У праграме створаны тры аб’екты тыпу date. Для першага (d1) выкарыстоўваўся канструктар па змоўчанні. Для другога (d2) выкарыстоўваўся канструктар, які ініцыялізаваў аб’ект трыма лікамі, уведзенымі з клавіятуры. Трэці аб’ект (d3) ініцыялізаваны радком. Для вываду трэцяга аб’екта выкарыстаны метад get_date_dm, які выводзіць толькі лік і месяц.


[1] Пры апісанні вектара ў якасці ўласцівасці класа нельга ініцыялізаваць элементы даных адразу ў дужках (vector <int> otm(3)), трэба ўласцівасці прысвоіць значэнне, якое ініцыялізуецца.

.