Лекции по обектно-ориентирано програмиране



страница11/16
Дата25.07.2016
Размер0.95 Mb.
#6568
ТипЛекции
1   ...   8   9   10   11   12   13   14   15   16

19. Влагане на класове.

един клас може да включва в себе си обекти от други класове като данни елементи; както е известно, когато обект от даден клас се дефинира, автоматично се извиква неговият конструктор; ако класът съдържа обекти елементи, в неговия конструктор трябва да се укаже как аргументите се предават към конструкторите на обектите елементи; обектите елементи се създават в този ред, в който са декларирани, преди да бъдат създадени обектите на включващия ги клас; начални стойности за обектите елементи могат да се задават чрез списък от инициализатори към конструктора на включващия ги клас; ако не е зададен списък от инициализатори, за обектите елементи автоматично се извиква конструктор с аргументи по премълчаване; след това те могат да бъдат променяни чрез съответните функции елементи за запис; типична грешка е да не е предвиден конструктор с аргументи по премълчаване за обекти елементи, за които не е зададен инициализатор, в резултат съответният обект елемент може да остане неинициализиран (въпреки, че за него е извикан служебен конструктор по премълчаване); от съображения за ефективност се препоръчва обектите елементи да се инициалират явно, с помощта на инициализатори;


Примерна програма:
#include

#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 ();

}




Сподели с приятели:
1   ...   8   9   10   11   12   13   14   15   16




©obuch.info 2024
отнасят до администрацията

    Начална страница