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


Структурно и модулно програмиране. Обектно-ориентирано програмиране



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

12. Структурно и модулно програмиране. Обектно-ориентирано програмиране.

практиката на програмирането е показала, че когато се съставят програми, най-трудното е откриването на грешки; една от първите причини за това е прекомерното използване на оператор goto в програмите; пръв Доналд Кнут защитава тезата срещу оператора goto и се счита, че той полага принципите на структурното програмиране;



структурно програмиране – подход за създаване на ясни, добре документирани и структурирани програми;
принципи на структурното програмиране:

  • принцип на визуалност и мнемоника (краснопис в програмирането);

  • принцип за програмиране без goto;

  • принцип за стандартизация на управлението;

  • програмата да се проектира предварително, преди да се кодира;

  • програмата да съдържа коментари;

  • разбиване на една програма на подпрограми – стъпка по стъпка да се детайлизира алгоритъма;

при структурното програмиране има три структури за управление:

  • последователно изпълнение (например в езика C операторите се изпълняват последователно);

  • селектиране (в C оператора if е основно средство);

  • повторение, изключва се goto (в C основно средство е цикъл while);

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

в резултат на развитието на подпрограмите се появява модул (например езика MODULA 2); при него явно се описва какви ресурси той може да обменя с други модули; модулът съдържа данни и подпрограми; в C и C++ модулът е програмна единица, която се съхранява в отделен първичен файл;

въвеждането на понятието модул позволява още по-големи програми;

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

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

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



13. Класове и обекти. Примерна програма.



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

данните, които са компоненти на класа, се наричат данни-елемнти, функциите, които са компоненти на класа, се наричат функции-елементи;

подобно на това, както същност от тип int се нарича променлива, то същност от потребителски дефиниран тип (клас) се нарича обект;

класовете дават възможност да се моделират явления, които имат атрибути, представени като данни-елементи, и варианти на поведение, представени като функции-елементи;

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

синтаксис на дефиниция на клас:

class име_на_клас

{

тяло_на_клас



} ;
примерна дефиниция на клас:

class Time {

public:

Time();


void setTime (int, int, int);

void printMilitary();

void printStandard();

private:


int hour;

int minute;

int second;

} ;


етикетите public и private се наричат спецификатори за достъп до елементите;

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

данните-елементи и функциите-елементи декларирани след private до следващия спецификатор за достъп се наричат закрити и те са достъпни само за функциите-елементи от този клас;

спецификаторите за достъп завършват с ‘:’, могат да се появяват многократно в дефиницията и в произволен ред; препоръчва се, обаче, в дефиницията на клас всеки спецификатор за достъп до елемент да се използва само веднъж, започвайки с public;

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

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

целите данни елементи hour, minute, second са достъпни само от функциите-елементи на класа;

обикновено данните-елементите са в частта private, а функциите-елементи в частта public;

след като класът е дефиниран, името му може да се използва за дефиниране на обекти от този клас;

например:

Time s, a[5], *p, &d = s;
примерна програма:

#include

class Time {

public:


Time();

void setTime (int, int, int);

void printMilitary();

void printStandard();

private:

int hour;

int minute;

int second;

} ;

Time::Time()



{ hour = minute = second = 0; }

void 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;

}

void Time::printMilitary()



{ cout << (hour<10 ? “0” : “”) << hour << “:”

<< (minute<10 ? “0” : “”) << minute << “:”

<< (second<10 ? “0” : “”) << second << endl; }

void Time::printStandard ()

{ cout << ( (hour==0 || hour ==12) ? 12 : hour % 12) << “:”

<< (minute<10 ? “0” : “”) << minute << “:”

<< (second<10 ? “0” : “”) << second << ((hour < 12) ? “ AM” : “ PM”)

<< endl;

}

void main ()



{ Time t; //при това дефиниране автоматично се извиква

//конструктора на класа Time

t.printMilitary();//резултат 00:00:00

t.printStandard();//резултат 12:00:00 AM

t.setTime (13, 27, 6);

t.printMilitary();//резултат 13:27:06

t.printStandard();//резултат 1:27:06 PM

t.setTime (99, 99, 99);

t.printMilitary();//резултат 00:00:00

t.printStandard();//резултат 12:00:00 AM

}

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



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

cout е стандартен обект, който е свързан със стандартния поток за извеждане, който най-често операционната система свързва с екрана; endl е манипулатор, можем вместо него да изведем ‘\n’ – разликата е, че манипулаторът изчиства буфера за извеждане, т.е. предизвиква незабавно извеждане на всички данни в буфера;


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

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

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

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

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

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






Сподели с приятели:
1   2   3   4   5   6   7   8   9   10   ...   16




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

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