Печатать книгуПечатать книгу

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

Сайт: Профильное обучение
Курс: Інфарматыка. 10 клас (Павышаны ўзровень)
Книга: § 22. Тып даных клас (class)
Напечатано:: Гость
Дата: Четверг, 2 Май 2024, 22:44

22.1. Паняцце класа

Мова праграміравання C++ мае вялікую колькасць розных тыпаў і структур даных (напрыклад: char, int, double, vector, list і г. д.), якіх дастаткова для рашэння адносна простых задач. Аднак для рашэння больш складаных праблем функцыяналу гэтых тыпаў можа не хапіць.

У С++ ёсць магчымасць вызначаць уласныя тыпы даных, якія будуць ужывацца для рашэння пэўнай задачы. Вы ўжо стваралі структуры, якія могуць выкарыстоўвацца для стварэння ўласных карыстальніцкіх тыпаў даных.

Структуры — гэта традыцыйны спосаб уяўлення складаных тыпаў даных, характэрны для парадыгмы структурнага праграміравання.

У аб’ектна-арыентаваным праграміраванні[1] тыпы даных могуць змяшчаць не толькі даныя, але і функцыі, якія могуць працаваць з гэтымі данымі. Такім тыпам даных з’яўляецца клас.


[1] З прынцыпамі аб’ектна-арыентаванага праграміравання вы пазнаёміцеся ў 11-м класе.  

У мове C структуры могуць толькі захоўваць даныя і не могуць мець метадаў для іх апрацоўкі. У C++, пасля праектавання класаў (выкарыстоўваючы ключавое слова class), Б’ёрн Страуструп разважаў пра тое, ці трэба, каб структуры (якія былі ўнаследаваны з мовы С) мелі звязаныя функцыі-члены. Пасля некаторых разважанняў ён вырашыў, што трэба. Таму сёння структуры і класы ў С++ маюць больш падабенства, чым адрозненняў.

Шмат якія распрацоўшчыкі лічаць, што такое рашэнне не было правільным, паколькі яно можа прывесці да рэальных праблем (напрыклад, з вылучэннем і ачысткай памяці). Таму рэкамендуецца выкарыстоўваць ключавое слова struct для структур, якія ўжываюцца толькі для захоўвання даных, і ключавое слова 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)), трэба ўласцівасці прысвоіць значэнне, якое ініцыялізуецца.

.

22.3. Прыклад работы з класам

Пры выкарыстанні аб’ектаў сістэма праграмавання Code::Blocks выдае падказкі для палёў і метадаў карыстальніцкіх класаў, гэтак жа як і для ўбудаваных класаў.

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

Прыклад 22.6. Апісаць клас IntNumber для работы з цэлым лікам. У класе вызначыць функцыі для рэалізацыі наступных метадаў: праверкі ліку на прастату, падліку колькасці лічбаў у ліку, «перавароту», атрымання працэнтаў ад ліку. Прадэманстраваць работу метадаў.

Этапы выканання задання

I. Зыходныя даныя: пераменная s — лік.

II. Вынік: дэманстрацыя работы метадаў класа.

III. Алгарытм рашэння задачы.

1. Ввод Увод зыходных даных.
2. Рэалізуем наступныя метады
.

2.1. Лагічная функцыя  simple() праверыць, ці з’яўляецца лік простым. Праверка ліку на прастату была рэалізавана ў прыкладзе 11.26. 
2.2. Функцыі kol_numbers() для падліку колькасці лічбаў у ліку (рэалізавана ў прыкладзе 8.17) і перавароту ліку perevorot() будуць вяртаць значэнні int
2.3. Функцыя percent(double z) для атрымання працэнтаў ад ліку будзе залежыць ад параметра (велічыня працэнта) і вяртаць тып double.

3. Вывад вынікаў.

IV. Апісанне пераменных: n – IntNumber, IntNumber – class.

Прыклад 22.6.

V. Праграма:

#include <iostream>

#include <сmath>

 

using namespace std;

 

class IntNumber

{

  int field;

  public:

    //канструктар класа

    IntNumber(int fi) {field = fi;}

    //атрыманне значэння ліку

    int get_num() {return field;}

  //праверка на прастату

    bool simple();

    //колькасць лічбаў ліку

    int kol_numbers();

    //пераварот ліку

    int perevorot();

  //працэнт ад ліку

    double percent(double z);

};

 

bool IntNumber::simple()

{

  int i = 2;

    while (field % i != 0 &&

           i * i <= field)

      i++;

    return(* i > field);

}

 

int IntNumber::kol_numbers()

{

  int i = 0;

  int s = field;

  while (> 0){

    i++;

    s /= 10;

  }

  return i;

}

 

int IntNumber::perevorot()

{

  int x = 0;

  int s = field;

    while (>= 1){

      x = x * 10 + s % 10;

      s /= 10;

  }

    return x;

}

 

double IntNumber::percent(double z)

{

  return field * z / 100;

}

 

int main()

{

  int a;

  cout << "vvedi chislo" << endl;

  cin >> a;

  IntNumber n(a);

  if (n.simple()){

    cout << "chislo " << n.get_num();

    cout << " - prostoe" << endl;

  }

  else {

    cout << "chislo " << n.get_num();

    cout << " - sostavnoe" << endl;

  }

  cout << "v chisle " << n.get_num();

  cout << " kol-vo cifr = " ;

  cout << n.kol_numbers() << endl;

  cout << "perevertysh chisla - ";

  cout << n.perevorot() << endl;

  double x;

  cout << "vvedi %" << endl;

  cin >> x;

  cout << x << "% ot chisla ";

  cout << n.get_num() << " - ";

  cout << n.percent(x) << endl;

  return 0;

}

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

Пытанні да параграфу

1. Што такое клас?

2. Для чаго прызначаны палі і метады класа?

3. Якія спецыяльныя метады выкарыстоўваюцца для атрымання доступу да ўласцівасцей класа?

4. Навошта выкарыстоўваецца канструктар?

Практыкаванні

    

1. Дапоўніце клас date (прыклад 22.5) пералічанымі магчымасцямі.

    1. Метад для атрымання колькасці дзён у месяцы.
    2. Метад для праверкі, ці з’яўляецца год высакосным.
    3. Метад для праверкі карэктнасці даты.
    4. Метад для атрымання нумара бягучага дня пры адліку ад 1.1.1900 (гл. прыклад 16.13).
    5. Канструктар з двума параметрамі, якія з’яўляюцца чыслом і месяцам, для года ўстанавіць бягучы.
    6. Прапануйце свае функцыі.

2. Дапоўніце клас IntNumber (прыклад 22.6) пералічанымі магчымасцямі.

    1.  Метад для праверкі ліку на тое, ці з’яўляецца ён поўным квадратам.
    2.  Метад для вылічэння фактарыяла ліку.
    3. Метад для праверкі ліку на тое, што ён з’яўляецца «іменным»:
    • простым лікам Мерсена (лік Мерсена можна паказаць у выглядзе 2n – 1);
    • лікам Армстранга (натуральны лік з k лічбаў з’яўляецца лікам Армстранга, калі сума яго лічбаў, узведзеных у k-ю ступень, роўна самому ліку, напрыклад 153 = 13 + 53 + 33, k = 3);
    • іншым цікавым лікам (гл. пр. 6 пасля § 8).

4. Метад для раскладання ліку на простыя множнікі.
5. Прапануйце свае функцыі.

3. Рэалізуйце клас для захоўвання часу. Дабаўце ў якасці метадаў тыя функцыі, якія былі рэалізаваны для адпаведнай структуры (прыклад 16.12).

4. Стварыце клас treugolnik1, які рэалізуе матэматычныя формулы для вылічэння плошчы трохвугольніка, перыметра трохвугольніка, сярэдняй лініі, радыусаў упісанай і апісанай акружнасцей і інш.