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


Използване на данни и функции елементи



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

17. Използване на данни и функции елементи.

закритите данни елементи на един клас могат да се променят само с помощта на функции елементи или приятелски функции на този клас; тези функции трябва да проверяват коректността на данните;


класовете обикновено съдържат открити функции елементи, чрез които клиентите на класа задават или получават стойностите на закритите данни елементи;
ако данните елементи са открити, те могат директно да бъдат записвани и четени от всяка функция в програмата; използването на открити данни елементи, обаче, не се препоръчва;
Пример с класа Time:
заглавен файл time.h
#ifndef TIME_H

#define TIME_H

class Time

{ public:

Time (int = 0, int = 0, int = 0);

void setTime (int, int, int);

void setHour (int);

void setMinute (int);

void setSecond (int);

int getHour ();

int getMinute ();

int getSecond ();

void printMilitary ();

void printStandard ();

private:

int hour;

int minute;

int second;

};

#endif
първичен файл time.cpp


#include

#include “time.h”

описание на функциите Time, setTime, printMilitary, printStandard



void Time::setHour (int h)

{ hour = (h>=0 && h < 24) ? h : 0; }

void Time::setMinute (int m)

{ minute = (m>=0 && m < 60) ? m : 0; }

void Time::setSecond (int s)

{ second = (s>=0 && s < 60) ? s : 0; }

int Time::getHour () { return hour; }

int Time::getMinute () { return minute; }

int Time::getSecond () { return second; }


първичен файл maintime.cpp
#include

#include “time.h”

void incrementMinutes (Time &, int);

void main ()


{ Time t;

t.setHour (17); t.setMinute (34); t.setSecond (25);

cout << “Час: “ << t.getHour () << endl

<< “Минута: “ << t.getMinute () << endl

<< “Секунда: “ << t.getSecond () << endl;

t.setHour (234); t.setMinute (43); t.setSecond (6373);

// hour = 0, minute = 43, second = 0

t.setTime (11, 58, 0);

incrementMinutes (t, 3);

t.printMilitary ();

}

void incrementMinutes (Time &tt, int count)



{ for (int i = 1; i<=count; i++)

{ tt.setMinute ( (tt.getMinute () + 1) % 60);

if (tt.getMinute () == 0)

tt.setHour ( (tt.getHour() + 1) % 24); }

}

в случая формалният параметър е псевдоним на фактическия параметър; достъпът до закритите данни елементи се осъществява с функциите get и set, което води до намаляване на ефективността; този недостатък може да се отстрани чрез използване на приятелски функции;


възможно е чрез открита функция елемент на клас да се върне в програмата неконстантен псевдоним на закрита данна елемент от този клас; пример:
#include

class Time {

public:

Time (int = 0, int = 0, int = 0);



void setTime (int, int, int);

int getHour ();

int& badsetHour (int);

private:


int hour, int minute, int second;

} ;


описание на Time и на setTime

int Time::getHour ()



{ return hour; }

int &Time::badsetHour (int h)

{ hour = (h >=0 && h < 24) ? h : 0;

return hour;//връща псевдоним на закритата данна елемент hour

} ;

void main ()



{ Time t;

int &hourRef = t.badsetHour (20);

//hourRef става псевдоним на закритата данна елемент hour

cout << t.getHour () << endl;

hourRef = 30; //не се прави проверка за коректност на данните

t.badsetHour (12) = 74; //аналогично

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

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

18. Константни обекти и константни елементи.

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


пример:

const Time noon (12, 0, 0);

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

class Time

{ public:

Time (int = 0, int = 0, int = 0);

void setTime (int, int, int);

void setHour (int);

void setMinute (int);

void 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, setTime, setHour, setMinute, setSecond

int Time::getHour () const { return hour; }



int Time::getMinute () const { return minute; }

int Time::getSecond () const { return second; }

void Time::printMilitary () const

{ …


описание на функция printMilitary

}



void Time::printStandard () const

{ …


описание на функция printStandard

}



void main ()

{ const Time t (19, 33, 52);

t.setHour (12); //грешка

t.setMinute (20); //грешка

t.setSecond (39); //грешка

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


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

class Increment

{ public:

Increment (int = 0, int = 1);

void addIncrement () { count += increment; }

void print () const;

private:

int count;

const int increment;

} ;


Increment::Increment (int c, int i) : increment (i)

//използвали сме инициализатор, за да дадем начална стойност на

// константната данна елемент;

{ count = c; }

void Increment::print () const

{ cout << “count = “ << count



<< “increment = “ << increment

<< endl;

}

void main ()



{ Increment value (10, 5);

value.print ();

for (int i = 1; i <=3; i++)

{ value.addIncrement ();

value.print ();

}

}



ако е необходимо да се дадат начални стойности на няколко константни данни елементи, те се изреждат в списък, разделени със запетаи; чрез инициализатори могат да се присвояват стойности и на неконстантни данни елементи;

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






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




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

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