#include
class Date
{ public:
Date (int = 1, int = 1, int = 1900);
void print () const;
private:
int month; int day; int year;
int checkDay (int);
} ;
Date::Date (int d, int m, int y)
{ if (m > 0 && m <=12) month = m;
else { month = 1;
cout << “Месец “ << m << “ е некоректен! Зададен е месец 1!”
<< endl;
}
year = y;
day = checkDay (d);
cout << “Конструктор на обекта Date “;
print (); cout << endl;
}
int Date::checkDay (int testday)
{ static int dayspermonth [13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30,
31, 30, 31} ;
if (testday > 0 && testday <= dayspermonth [month])
{ return testday; }
if (month == 2 && testday == 29 && ( year % 400 == 0 ||
( year % 4 == 0 && year % 100 != 0))) return testday;
cout << “Денят “ << testday << “ е некоректен! Зададен е ден 1!”
<< endl;
return 1;
}
void Date::print () const
{ cout << day << ‘/’ << month << ‘/’ << year; }
class Employee
{ public:
Employee (char *, char *, int, int, int, int, int, int);
void print() const;
private:
char firstname[25];
char lastname[25];
Date birthdate;
Date hiredate;
} ;
Employee::Employee (char *fname, char *lname, int bday, int bmonth, int byear, int hday, int hmonth, int hyear) : birthdate (bday, bmonth, byear), hiredate (hday, hmonth, hyear)
//използвали сме инициализатори, за да зададем аргументи за //конструкторите на обектите елементи
{ int length = strlen (fname);
length = (length < 25) ? length : 24;
strncpy (firstname, fname, length);
firstname[length] = ‘\0’;
length = strlen (lname);
length = (length < 25) ? length : 24;
strncpy (lastname, lname, length);
lastname[length] = ‘\0’;
cout << “Конструктор на обекта Employee: “ << firstname << ‘ ‘
<< lastname << endl;
}
void Employee::print () const
{ cout << lastname << “, “ << firstname << endl
<< “Постъпил на работа: “;
hiredate.print ();
cout << “ Роден на: “;
birthdate.print ();
cout << endl;
};
void main ()
{ Employee e (“Иван”, “Петров”, 24, 7, 49, 12, 3, 88);
e.print ();
Date d (35, 14, 94);
d.print ();
}
20. Приятелски функции и приятелски класове.
Приятелските функции на един клас се дефинират извън областта на действие на този клас, но имат право на достъп до закритите елементи (private) и защитените елементи (protected) на дадения клас;
функция или цял клас могат да бъдат обявени като приятели на друг клас; приятелските функции се използват за повишаване на производителността, например при предефиниране на операции или при създаване на класове итератори;
обектите от класа на итератора се използват за да избират последователно елементи или да изпълняват операции над елементите на обект от класа контейнер; типични операции върху елементи на обект от клас контейнер са вмъкване, изключване, търсене, сортиране, проверка за наличие на елемент и др.; примери за класове контейнери са масиви, стекове, опашки, свързани списъци;
за да се обяви, че функция е приятел на клас преди прототипа на функцията в описанието на класа се записва ключовата дума friend;
за да се обяви например, че ClassTwo е приятел на ClassOne, трябва в описанието на ClassOne да се запише:
friend ClassTwo;
в този случай всички функции елементи на ClassTwo стават приятелски функции за ClassOne;
обикновено класът на итераторите се обявява като приятелски на класа на контейнерите;
обявяване на приятелство може да стане на произволно място в описанието на класа; препоръчва се, обаче, това да става в началото, преди спецификаторите за достъп до елемент;
някои програмисти смятат, че приятелството вреди на скриването на информация и отслабва обектно-ориентирания подход;
Примерна програма:
#include
class Count
{ friend void setx ( Count &, int);
public:
Count () { x = 0;}
void print () const { cout << x << endl; }
private:
int x;
} ;
void setx ( Count &c, int value)
{ c.x = value; }
void main ()
{ Count object;
object.print ();
setx (object, 8);
object.print ();
}
ако функцията не беше обявена за приятел на класа Count, този начин на използване на данната елемент ще доведе до съобщение за грешка;
21. Използване на указателя this.
Всеки обект може да определи своя собствен адрес с помощта на указателя this; този указател неявно се използва за достъп както до данните елементи, така и до функциите елементи на обекта; също така, той може да се използва и явно;
указателят this се инициализира автоматично да сочи към обекта,
за който се извиква функция елемент; типът на указателя this зависи от типа на обекта и от това, обявена ли е функцитя елемент, в която се използва this, за const;
в неконстантна функция елемент, указателят this има тип
тип_на_обекта *const, т.е. указателят е константен;
в константна функция елемент, указателят this има тип
const тип_на_обекта *const, т.е. това е константен указател, който сочи към константа;
всяка функция елемент има достъп до указателя this на обекта, за който е извикана тази функция елемент;
с цел икономия на памет, за всяка функция елемент съществува само едно копие на класа и тази функция елемент се извиква от всеки обект на даден клас; от друга страна, всеки обект има собствено копие на данните елементи на класа;
пример за използване на this:
#include
class Test
{ public:
Test (int = 0);
void print () const;
private:
int x;
}
Test::Test (int a) { x = a; }
void Test::print () const
{ cout << x << endl;
cout << this->x << endl;
cout << (*this).x << endl;
}
void main ()
{ Test a (12);
a.print ();
}
в израза (*this).x кръглите скобки са задължителни, тъй като операцията ‘.’ има по-голям приоритет от операцията *; във функцията елемент print по три начина (които на машинно ниво не се различават) се обръщаме към данната елемент x на обекта Time;
едно интересно приложение на указателя this е предотвратяване на присвояване на един обект сам на себе си; при предефиниране на операции, самоприсвояването може да стане причина за сериозни грешки в случаите, когато обектът съдържа указател към динамично разпределена памет;
друго приложение на указателя this е възможността за слепване на извиквания на функция елемент;
примерна програма (с класа Time)
#include
class Time
{ public:
Time (int = 0, int = 0, int = 0);
Time& setTime (int, int, int);
Time& setHour (int);
Time& setMinute (int);
Time& setSecond (int);
int getHour () const;
int getMinute () const;
int getSecond () const;
void printMilitary () const;
void printStandard () const;
private:
int hour;
int minute;
int second;
} ;
Time::Time ( int h, int m, int s)
{ setTime (h, m, s); }
Time& Time::setTime (int h, int m, int s)
{ hour = (h>=0 && h < 24) ? h : 0;
minute = (m>=0 && m < 60) ? m : 0;
second = (s>=0 && s < 60) ? s : 0;
return *this;
}
Time& Time::setHour (int h)
{ hour = (h>=0 && h < 24) ? h : 0;
return *this;
}
Time& Time::setMinute (int m)
{ minute = (m>=0 && m < 60) ? m : 0;
return *this;
}
Time& Time::setSecond (int s)
{ second = (s>=0 && s < 60) ? s : 0;
return *this;
}
…
описание на функциите getHour, getMinute, getSecond,
printMilitary, printStandard
…
void main ()
{ Time t;
t.setHour (18).setMinute (30).setSecond (22);
//операцията ‘.’ е ляво-асоциативна
t.printMilitary ();
t.setTime (20, 20, 20).printStandard ();
}
Сподели с приятели: