Част 12. Пример за клас, който преставя часа и минутите
За да затвърдим знанията за класовете и техните функции в тази лекция ще стартираме спецификацията на един клас, който представя времето като часове и минути. Идеята за този материал е взета от прекрасната книга на Лафоор [1].
1. Времето като клас. Времето ще го изразяваме с две числа - от 0 до 23 за часовете и от 0 до 59 за минутите. Следователно ще имаме две променливи на класа - hours и minutes. Това са целочислени променливи на класа и те са дефинирани като частен член (private member) - променлива или функция, които са достъпни само в собствения си клас. Затова тяхната настройка, показване и промяна ще се извършват само с функции на класа, които са в публични членове (public member) на класа.
Функциите, които ни трябват са - set() - за въвеждане на времето, display() - за показване на времето и add(airtime at1, airtime at2) - за събиране на две времена и присвояванета на резултата към времето на обекта. Например с последната функция можем да изчислим часа на пристигане, ако е зададен началният час на тръгване и продължителността на пътуването.
Пълната дефиниция на класа е дадена по-долу.
class
airtime
{
private:
int minutes; // 0 to 59
int hours; // 0 t0 23
public:
void set()
{
char dummy; // for colon
cout << "Enter time (format 23:59): ";
cin >> hours >> dummy >> minutes;
}
void display()
{
cout << hours << ':'
<< setfill('0')
<< setw(2) << minutes;
}
void add(airtime at1, airtime at2)
{
minutes = at1.minutes + at2.minutes; // add minutes
hours = at1.hours + at2.hours;
// add hours
if(minutes > 59)
// if carry,
{
minutes = minutes - 60;
// adjust minutes
hours = hours + 1;
// and hours
}
if(hours > 23)
// if carry,
hours = hours - 24;
// adjust hours
}
};
// class airtime
Обърнете внимание на променливата dummy във функцията set(). Със същата променлива се запознахме и в част 10 на тази поредица и тя служи да прочете двете точки при въвеждане на времето като например 12:34.
2. Още за манипулаторите. В част четвърта на тази поредица се запознахме с манипулатора endl (endl manipulator) и видяхме, че манипулаторите са обекти, които могат да се вкарват в потока (stream) и променят неговото форматиране. Във функцията display() се използват два манипулатора - setfill('0') и setw(2). Първият манипулатор вкарва водеща нула към минутите, докато вторият определя две позиции на екрана да се запазват за тези минути. Това позволява 3 часа и 4 минути да се показват на екрана като 3:04, а не като 3:4. Без setfill('0') в израза cout << hours << ':' << setfill('0') << setw(2) << minutes; часът ще се показва като 3: 4, с празен интервал преди числото 4. Разбира се в манипулатора setfill можем да сложим кой и да е символ и той ще запълва числото на часовете до ширината, определена от setw.
3. Функции с аргументи. В предишната част се запознахме с функциите с аргументи. В дефинирания клас по-горе такава функция е add(airtime at1, airtime at2). Тя има два аргумента, at1 и at2, от тип airtime, който е типът на класа. Тя събира две времена и резултатът се присвоява на обекта, с който се извиква функцията. Обърнете внимание, че този замисъл е коренно различен от замисъла при функцията add(complex_number compl_num) от предишната част, която прибавя комплексно число към обекта комплексно число, чиято функция се извиква.
Във функцията add(airtime at1, airtime at2)първо се събират минутите и часовете на двата обекта at1 и at2 и тези суми се присвояват на променливите на класа minutes и hours, а те са фактически променливи на обекта, с който се извиква функцията. Ако получените минути са по-големи от 59, те се намаляват с 60 и часът на обекта се увеличава с единица. Ако часът надмине 24, то от него се изважда 24: това на практика прави часът на следващия ден.
Като видяхме от предишния материал, извикването на функцията за даден обект се извършва с помощта на точковия оператор (class member access operator) по следния начин: t3.add(t1, t2);. Пълният код на примерната програма, взет от [1], е следният:
//
timeadd.cpp
//
a class that models a time data type
//
includes member function to add two times
#include
<iostream.h>
#include
<iomanip.h>
// for setw(), etc.
#include
<conio.h>
//for getche()
class
airtime
{
private:
int minutes; // 0 to 59
int hours; // 0 t0 23
public:
void set()
{
char dummy; // for colon
cout << "Enter time (format 23:59): ";
cin >> hours >> dummy >> minutes;
}
void display()
{
cout << hours << ':'
<< setfill('0')
<< setw(2) << minutes;
}
void add(airtime at1, airtime at2)
{
minutes = at1.minutes + at2.minutes; // add minutes
hours = at1.hours + at2.hours;
// add hours
if(minutes > 59)
// if carry,
{
minutes = minutes - 60;
// adjust minutes
hours = hours + 1;
// and hours
}
if(hours > 23)
// if carry,
hours = hours - 24;
// adjust hours
}
};
// class airtime
void
main()
{
airtime t1, t2, t3; // create three airtime
variables
char choice;
do
{
cout << "For t1, ";
t1.set();
// set t1
cout << "For t2, ";
t2.set();
// set t2
t3.add(t1, t2); // add t1 and t2, result in t3
cout << "t3 = ";
t3.display(); // display
t3
cout << "\nDo another (y/n)? ";
cin >> choice;
} while(choice != 'n');
// stop the flow on the monitor
getch();
} //end main
В главната функция на програмата се декларират три променливи at1, at2 и at3 от тип airtime. В един цикъл се вкарват стойностите на първите две променливи, после те се събират и резултатът се присвоява на третата променлива, която се показва на екрана.
4. Функцията set() с аргументи. Тази функция може да бъде променена за да инициализира променливите на обекта с предварително зададени стойности по следния начин:
void
set(int h, int m) // (values supplied
by arguments)
{
hours = h; minutes = m; // set airtime value
}
Тогава и главната функция на програмата трябва да се промени по следния начин:
void
main()
{
int hhs, mms; // variables for user-supplied
values
char dummy; // for colon
airtime t1, t2, t3; // create three airtime
variables
char choice;
do
{
cout << "For t1, ";
cout << "For t1, enter time (format 23:59): ";
cin >> hhs >> dummy >> mms;
t1.set(hhs, mms);
// set t1 values
cout << "For t2, enter time (format 23:59): ";
cin >> hhs >> dummy >> mms;
t2.set(hhs, mms);
// set t2 values
t3.add(t1, t2); // add t1 and t2, result in t3
cout << "t3 = ";
t3.display();
// display t3
cout << "\nDo another (y/n)? ";
cin >> choice;
} while(choice != 'n');
// stop the flow on the monitor
getch();
} //end main
Аргументите на една функция могат да бъдат от всеки тип. До тук видяхме че те могат да бъдат от типовете complex_number (дефиниран в предишната част), airtime във функцията add(airtime at1, airtime at2) и int в функцията set(int h, int m).
Досега функциите бяха дефинирани с ключовата дума void, която показва че функцията не връща стойност. Функциите могат да връщат стойности, но с това ще се запознаем в следващите материали по C++.
Да не забравяме и подробното обяснение на главната функция на програма main, което беше дадено в част 5. Там бе показана тази функция във вида int main(int argc, char * argv[]), т.е. тя връща целочислена стойност и има два аргумента, единият от които реално представлява един масив от стойности.
5. Предаване на аргументи по стойности. В двете функции, разгледани в тази част, аргументите се предават по стойности (passing by value). Това означава, че програмата създава чисто нови променливи в стека. Тези променливи съдържат стойностите на предаваните аргументи. В тялото на функцията можем да променяме стойностите на аргументите, но това не води до промени на оригиналните аргументи, които се предават при извикване на функцията. Тук трябва да се отбележи, че с масивите въпросът не стои по този начин, защото реално в програмата се предава указател към масива, който указател не може да се променя, но самите стойности на елементите на масива могат!
Но с масивите и другите два начина за предаване на аргументи - като предаване по връзка (passing by reference) и предаване на указателите на аргументите ще се запознаем в следващите материали.
Литература
[1] Robert Lafore; C++ Interactive Course. Waite Group Press, Macmillan Computer Publishing, 1996.
Автор: Проф. Процесор Аритметиков
Keywords: С++,
OOP programming , C++ , Classes , Inheritance , Reusability , Creating
New Data Types , Polymorphism and Overloading
Ключови думи: клас
, обект, обектно ориентирано програмиране , полиморфизъм switch if else
?