Главная->Інформатика та програмування->Содержание->Преобразования объектов клас сов в объекты других классов

ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 8) онлайн

Преобразования объектов клас сов в объекты других классов

Что мы можем сказать о преобразованиях между объектами различных, опреде- ленных пользователем классов? Для них применяются те же два метода преобра- зования, что и для преобразований между основными типами и объектами опре-

деленных пользователем классов. То есть вы можете использовать конструктор с одним аргументом или операцию преобразования. Выбор зависит от того, хотите ли вы записать функцию преобразования в классе для исходного объекта или для объекта назначения. Например, предположим, что мы записали:

objecta = objectb;

где objecta — объект класса A, a objectb — объект класса B, Где же расположить функцию преобразования, в классе А (это класс назначения, так как objecta полу- чает значение) или в классе В? Мы рассмотрим оба варианта.

Две формы времяисчисления

В нашей программе мы будем производить преобразования между двумя спо- собами исчисления времени: 12-часовым и 24-часовым. Эти способы еще назы- вают гражданским временем и военным временем. Класс time12 будет предназна- чен для гражданского времени, которое используется в цифровых часах и табло отправки и прибытия самолетов. Мы предполагаем, что нам не нужны секунды, поэтому в классе time12 мы будем использовать только часы (от 1 до 12) и мину- ты, а также обозначение времени суток «a.m.» и «p.m.», что означает до полудня и после полудня соответственно. Класс time24, предназначенный для более точ- ных целей, таких, как воздушная навигация, использует часы (от 00 до 23), мину- ты и секунды. В табл. 8.1 показаны различия между двумя формами время исчис- ления.

Таблица 8.1. 12-часовое и 24-часовое время 12-часовое время         24-часовое время

12:00 a.m. (полночь)    00:00

12:01 a.m.           00:01

1:00 a.m.             01:00

6:00 a.m.             06:00

11:59 a.m.           11:59

12:00 p.m. (полдень)   12:00

12:01 p.m.          12:01

6:00 p.m.             18:00

11:59 p.m.          23:59

Заметим, что 12 часов ночи (полночь) в гражданском времени соответству- ют 00 часам в военном времени. В гражданском времени 0 часов нет.

Функция в исходном объекте

В нашей первой программе мы рассмотрим случай, когда функция преобразова- ния расположена в исходном классе. В этом случае она будет реализована в виде операции преобразования. Приведем листинг программы TIMES1.

// times1.cpp

// программа перевода времени в 24-часовом написании

// в 12-часовое

#include <iostream>

#include <string>

using namespace std;

///////////////////////////////////////////////////////////

class time12

{

  private:

    bool pm;

    int hrs;

    int mins;

  public:

    time12 ( ) : pm ( true ), hrs ( 0 ), mins ( 0 )

      { }

    time12 ( bool ap, int h, int m ) : pm ( ap ), hrs ( h ), mins ( m )

      { }

    void display ( ) const

      {

        cout << hrs << ':';

        if ( mins < 10 )

          cout << '0';

        cout << mins << ' ';

        string am_pm = pm ? "p.m." : "a.m.";

        cout << am_pm;

      }

};

///////////////////////////////////////////////////////////

class time24

{

  private:

    int hours;

    int minutes;

    int seconds;

  public:

    time24 ( ) : hours ( 0 ), minutes ( 0 ), seconds ( 0 )

      { }

    time24 ( int h, int m, int s ) : hours ( h ), minutes ( m ), seconds ( s )

      { }

    void display ( ) const

      {

        if ( hours < 10 ) cout << '0';

        cout << hours << ':';

        if ( minutes < 10 ) cout << '0';

        cout << minutes << ':';

        if ( seconds < 10 ) cout << '0';

        cout << seconds;

      }

    operator time12 ( ) const;

};

///////////////////////////////////////////////////////////

time24::operator time12 ( ) const

{

  int hrs24 = hours;

  bool pm = hours < 12 ? false : true;

 

  int roundMins = seconds < 30 ? minutes : minutes + 1;

  if ( roundMins == 60 )

  {

roundMins = 0;

    ++hrs24;

    if ( hrs24 == 12 ||hrs24 == 24 )

      pm = ( pm == true ) ? false : true;

  }

  int hrs12 = ( hrs24 < 13 ) ? hrs24 : hrs24 – 12;

  if ( hrs12 == 0 )

  {

    hrs12 = 12;

    pm = false;

  }

  return time12 ( pm, hrs12, roundMins );

}

///////////////////////////////////////////////////////////

int main ( )

{

  int h, m, s;

 

  while ( true )

  {

    cout << "Введите время в 24-часовом формате: \n";

    cout << "  Часы (от 0 до 23): "; cin >> h;

    if ( h > 23 )

      return ( 1 );

    cout << "  Минуты: "; cin >> m;

    cout << "  Секунды: "; cin >> s;

 

    time24 t24 ( h, m, s );

    cout << "Исходное время: ";

    t24.display ( );

 

    time12 t12 = t24;

 

    cout << "\nВ 12-часовом формате: ";

    t12.display ( );

    cout << "\n\n";

  }

  return 0;

}

 

В функции main() программы TIMES1 мы определили объект класса time24, названный t24, и присвоили ему значения часов, минут и секунд, полученные от пользователя. Мы также определили объект класса time12, названный t12, и ини- циализировали его значением объекта t24 в строке

time12 t12 =t24;

Так как это объекты различных классов, то для осуществления присваива- ния необходимо преобразование. Мы определили здесь операцию преобразова- ния в классе time24. Вот ее объявление:

time24::operator time12 ( ) const;

Эта функция преобразует вызывающий ее объект в объект класса time12 и возвращает функции main() объект, который будет затем присвоен перемен- ной t12. Пример взаимодействия с программой TIMES1:

Введите время в 24-часовом формате: Часы (от 0 до 23): 17 Минуты: 59 Секунды: 45 Исходное время: 17:59:45 В 12-часовом формате: 6:00 p.m.

Значение секунд округляется, и мы получим 6:00 p.m. При попытке ввода значения часа больше 23 программа завершится.

Функция в объекте назначения

Давайте рассмотрим, как это же преобразование выполняется, если функция преобразования находится в классе назначения. В этой ситуации используется конструктор с одним аргументом. Однако все усложняется тем фактом, что кон- структор класса назначения должен иметь доступ к данным исходного класса для выполнения преобразования. Поля класса time24 — hours, minutes и seconds — объявлены как private, поэтому мы должны написать специальные методы в клас- се time24, которые будут позволять к ним прямой доступ. Это методы getHrs(), getMins() и getSecs().

Листинг программы TIMES2:

//times2.cpp

//converts from time24 to time12 using constructor in time12

#include <iostream>

#include <string>

using namespace std;

////////////////////////////////////////////////////////////////

class time24

   {

   private:

      int hours;                     //0 to 23

      int minutes;                   //0 to 59

      int seconds;                   //0 to 59

   public:                           //no-arg constructor

      time24() : hours(0), minutes(0), seconds(0)

         {  }

      time24(int h, int m, int s) :  //3-arg constructor

              hours(h), minutes(m), seconds(s)

         {  }

      void display() const           //format 23:15:01

         {

         if(hours < 10)    cout << '0';

         cout << hours << ':';

         if(minutes < 10)  cout << '0';

         cout << minutes << ':';

         if(seconds < 10)  cout << '0';

         cout << seconds;

         }

      int getHrs() const   { return hours; }

      int getMins() const  { return minutes; }

      int getSecs() const  { return seconds; }

   };

////////////////////////////////////////////////////////////////

class time12

   {

private:

      bool pm;                       //true = pm, false = am

      int hrs;                       //1 to 12

      int mins;                      //0 to 59

   public:                           //no-arg constructor

      time12() : pm(true), hrs(0), mins(0)

         {  }

      time12(time24);                //1-arg constructor

                                     //3-arg constructor

      time12(bool ap, int h, int m) : pm(ap), hrs(h), mins(m)

         {  }

      void display() const

         {

         cout << hrs << ':';

         if(mins < 10)  cout << '0';  //extra zero for "01"            

         cout << mins << ' ';

         string am_pm = pm ? "p.m." : "a.m.";

         cout << am_pm;

         }

   };

//--------------------------------------------------------------

time12::time12( time24 t24 )         //1-arg constructor

   {                                 //converts time24 to time12

   int hrs24 = t24.getHrs();         //get hours

                                     //find am/pm

   pm = t24.getHrs() < 12 ? false : true;

                                                     

   mins = (t24.getSecs() < 30) ?     //round secs

                         t24.getMins() : t24.getMins()+1;

   if(mins == 60)                    //carry mins?

      {

      mins=0;

      ++hrs24;

      if(hrs24 == 12 || hrs24 == 24)      //carry hrs?

         pm = (pm==true) ? false : true;  //toggle am/pm

      }

   hrs = (hrs24 < 13) ? hrs24 : hrs24-12; //convert hrs

   if(hrs==0)                        //00 is 12 a.m.

      { hrs=12; pm=false; }

   }

////////////////////////////////////////////////////////////////

int main()

{

   int h, m, s;

 

   while(true)

      {                              //get 24-hour time from user

      cout << "Enter 24-hour time: \n";

      cout << "   Hours (0 to 23): "; cin >> h;

      if(h > 23)                     //quit if hours > 23

         return(1);

      cout << "   Minutes: ";  cin >> m;

      cout << "   Seconds: ";  cin >> s;

 

      time24 t24(h, m, s);           //make a time24

      cout << "You entered: ";       //display the time24

      t24.display();

 

      time12 t12 = t24;              //convert time24 to time12

 

      cout << "\n12-hour time: ";    //display equivalent time12

      t12.display();            

      cout << "\n\n";

      }

   return 0;

}

Функцией преобразования здесь является конструктор с одним аргументом из класса time12. Она устанавливает для объекта, ее вызвавшего, значение, соот- ветствующее значению объекта класса time24, полученному в качестве аргумен- та. Это работает во многом так же, как и операция преобразования в программе TIMES1, за исключением того, что здесь возникает трудность с доступом к полям объекта класса time24, и нам необходимо использовать методы getHrs() и ему по- добные.

Функция main() программы TIMES2 такая же, как в программе TIMES1. В этой строке вновь происходит преобразование типов от time24 к time12, но уже с ис- пользованием конструктора с одним аргументом:

time12 t12 = t24;

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

 

20