ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В 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;
Результат работы программы будет таким же. Все различия находятся в ко- де, где предпочтение при выполнении отдается конструктору объекта назначе- ния, а не операции преобразования исходного объекта.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
