Програмен език C++
Част 32

 Аргументи на конструктора
(Constructor Arguments)
.
(съдържание)

В тази лекция ще бъдат разгледани конструкторите с аргументи, както и една особеност на конструктора без аргументи.

!Не знам защо в повечето книги по C++ не пише изрично, че конструкторът може да бъде само в public: частта на класа. Ако той се постави в private: частта на класа, компилаторът не може да разпознае инициализирането на обектите и дава съобщение (например в следващата програма) от рода на 'airtime::airtime(int,int)' is not accessible.


1. Двуаргументен конструктор (A Two-Argument Constructor). Може би си спомняте класа за време, въведен в лекция 12? В програмата timeadd.cpp времето се наглася с функцията на класа void set(). В програма се дефинират и три обекта на класа с твърдението airtime t1, t2, t3;. Понеже няма написан от програмиста конструктор компилаторът използва в това твърдение конструктора по подразбиране (default constructor), който бе споменат в края на предишната лекция.

Как би изглеждал конструктор с аргументи, ако искаме при създаване на обект от класа да нагласим и двете му променливи - minutes и hours? По аналогия с предишния пример за инициализиращ лист в конструктора той би бил:

  // two-argument constructor
  airtime(int h, int m) : hours(h), minutes(m)
  { }

Инициализиращият лист в конструктора изглежда подобен на този от предишната лекция, с промените описани там - запетайката, която разделя двете променливи в инициализиращия лист - hours(h), minutes(m). Новото са аргументите h и m, след името на конструктора: те са поставени в скоби и разделени със запетая - airtime(int h, int m).  Ето и цялата програма, която е взета от курса на Лафоор [1]:

// timecon.cpp
// class models time data type; uses constructor
#include <iostream.h>
#include <conio.h>                     // for getch()

class airtime
{
   private:
      int hours;       // 0 to 23
      int minutes;     // 0 to 59

   public:
      // two-argument constructor
      airtime(int h, int m) : hours(h), minutes(m)
      { }

      void display()
      {
         cout << hours << ':' << minutes;
      }
};

void main()
{
   airtime t1(7, 54);    // initialize t1

   cout << "\nt1 = ";
   t1.display();         // display t1

   getch();
}   // main()

В главната функция се дефинира един обект на класа, t1, и веднага се инициализира да показва 7 часа и 54 минути. Новото е дефиницията от вида airtime t1(7, 54);, където след името на обекта, в скоби стоят инициализиращите стойности, разделени със запетая. Това много прилича на извикване на функция, но лесно се разбира, че не е, защото при едно евентуално извикване типа на обекта (името на класа) не би стояло пред извикването.

Обърнете внимание, че конструкторът не е написан във вида

 airtime(int h, int m)    // The Wrong Way!!!
 {
   hours = h;
   minutes = m;
 }

Има много причини това да не се прави по този начин, но засега си припомнете разсъжденията от предишната лекция.

2. Конструктор без аргументи (A No-Argument Constructor). Ако в горната програма променим стария инициализиращ ред в главната функция на програмата чрез добавяне на ", t2" в него и така се опитаме да дефинираме още един обект от класа airtime със следния ред:

airtime t1(7, 54), t2;    // initialize t1 and t2?

то ще получим следното съобщение от компилатора:

Could not find a match for 'airtime::airtime()'.

това е така, защото самото написване на двуаргументния конструктор от програмиста води до заменяне на конструктора по подразбиране (default constructor) с този двуаргументен конструктор. За да можем да дефинираме обекти от този клас без да ги инициализираме по двете променливи е необходимо да добавим наш конструктор без аргументи във вида:

  // no-argument constructor
  airtime()
  { }

Това на практика означава, че може да има повече от един конструктор (те имат едно и също име), които се различават по своя списък на аргументи. (Спомнете си т.н. презаредени функции (Overloaded Functions) от лекция 25.)

3. Няколко конструктора. Ето една примерна елементарна програма, в която класа richman има няколко конструктора:

// richman.cpp
// multiple constructors
#include <iostream.h>
#include <conio.h>               // for getch()

class richman
{
    private:
      string name;
      int money;

    public:
      richman() : name("Jack"), money(0)
      {  }

      richman(int m) : name("Angel"), money(m)
      {  }

      richman(string n) : name(n), money(-1)
      {  }

      richman(string n, int m) : name(n), money(m)
      {  }

      void display()
      {
        cout << name << " has M$" << money << endl;
      }
};  // class richman

void main()
{
   richman plamen("Plamen", 10), sasha("Sasha", 1),
           angel(100), peter("Peter"), jack;

   plamen.display();
   sasha.display();
   angel.display();
   peter.display();
   jack.display();

   getch();

}  // main()

В главната функция се създават пет обекта като само един, jack, не се инициализира с някакви стойности, освен тези, които са зададени в конструктора. Първите два се инициализират с името и парите, третият само с парите, а четвъртият само с името. Както казахме, петият не се инициализира в главната функция, а само в конструктора по подразбиране (този без аргументи), където на името се дава стойността Jack, а на парите 0. Изходът от програмата на екрана е следният:

Plamen has M$10
Sasha has M$1
Angel has M$100
Peter has M$-1
Jack has M$0

Видяхме в тази лекция, че конструкторите могат да имат аргументи, че може да има няколко конструктора и ако ние напишем свои конструктори, трябва и да напишем и конструктор без аргументи, защото конструкторът по подразбиране се заменя с нашите.

.
(съдържание)
.
Литература
.
[1] Robert Lafore; C++ Interactive Course. Waite Group Press, Macmillan Computer Publishing, 1996.
.
Автор: Проф. Процесор Аритметиков
.
[ това е материал от брой 31 от юни 2009 г на списание "Коснос" www.kosnos.com ]

Keywords: С++,  OOP programming , C++ , Classes , Inheritance , Reusability , Creating New Data Types , Polymorphism and Overloading
Ключови думи: клас , обект, обектно ориентирано програмиране , полиморфизъм switch if else ?