§ 2. Класы

2.2. Канструктары

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

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

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

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

У канструктару можа быць выкарыстаны cпіс ініцыялізацыі палёў класа. Спіс ініцыялізацыі размяшчаецца пасля параметраў канструктара. Ён пачынаецца з двукроп'я (:), а затым значэнне для кожнага поля паказваецца ў круглых дужках. У целе канструктара не трэба выконваць аперацыі прысвойвання, таму цела канструктара можа быць пустым. Спіс ініцыялізацыі членаў класа не заканчваецца кропкай з коскай (прыклад 2.4).

Кожны метад класа няяўна ўтрымлівае ў якасці поля даных паказальнік:

IмяКласа *this;

З яго дапамогай метад класа вызначае, з данымі якога аб'екта яму трэба будзе працаваць. Паказальнік this можна выкарыстоўваць у канструктарах (прыклад 2.5).

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

Прыклад 2.3. Даданне канструктараў у клас Student.

class Student

{

  private:

  /** палі для захоўвання прозвішча

      і назвы горада **/

    string fam, gorod;

  /// поле - год нараджэння

    int god_r;

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

  public:

  /// канструктар па змоўчанні

     Student ();

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

   Student (string f, string g, int r,

            int n0, int n1, int n2);

  /// метад для вылічэння сумы адзнак

    int summ();

  /// сетэры для задання значэння палёў

    void set_fam(string f);

    void set_gorod(string g);

    void set_god_r(int r);

    void set_otm(vector <int> d);

  /** гетэр для атрымання радка

     Прозвішча Горад Сума балаў **/

    string get_fam_gor_summ();

};

Student::Student()

{

    gorod = "Мiнск";

    god_r = 2005;

}

 

Student::Student (string f, string g,

      int r, int n0, int n1, int n2)

{

    fam = f;

    gorod = g;

    god_r = r;

    otm[0] = n0;

    otm[1] = n1;

    otm[2] = n2;

}

Функцыя для ўводу даных з выкарыстаннем канструктара зменіцца наступным чынам:

void vvod1 (vector <Student> &d)

{

  ifstream fin ("input.txt");

  int r;

  fin >> r;

  fin.ignore();

  d.resize(r);

  /** Счытванне даных з файла і

      вызначэнне аб'ектаў з

      выкарыстаннем канструктара **/

  for (int i = 0; i < r; i++){

    string t_str, g_str;

    fin >> t_str;

    fin >> g_str;

    int t_int;

    fin >> t_int;

    int b0, b1, b2;

    fin >> b0 >> b1 >> b2;

    d[i] = Student(t_str, g_str,

               t_int, b0, b1, b2);

  }

}

Прыклад 2.4. Выкарыстанне спісу ініцыялізацыі пры апісанні канструктараў у класе Student.

/// канструктар па змоўчанні

  Student () : gorod ("Мiнск"), god_(2005) {}

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

  Student (string f, string g, int r,

           int n0, int n1, int n2) :

              fam(f), gorod (g), 

              god_r (r), 

              otm ({n0, n1, n2}) {}

Пераменныя ў спісе ініцыялізацыі атрымліваюць свае значэннi не ў тым парадку, у якім яны пазначаны, а ў тым парадку, у якім абвешчаны ў класе. Таму пры выкарыстанні спісаў ініцыялізацыі лепш захоўваць той жа парадак палёў, які зададзены пры апісанні класа.

Прыклад 2.5. Выкарыстанне паказальніка this у канструктару класа Date.

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

{

    this -> d = t_d;

    this -> m = t_m;

    this -> g = t_g;

}