Лекция №

Вид материалаЛекция
3.3Проектирование файлов интерфейсов классов. Лекция № 13.
Файлы интерфейсов производных классов
Файл управления
Подобный материал:
1   2   3   4   5   6   7   8   9   10   11

3.3Проектирование файлов интерфейсов классов. Лекция № 13.

Файл интерфейса базового класса


Спроектируем базовый класс ind. Поместим index и kol в часть private, т.к. они используется только элементами-функциями данного класса, а im_f и элементы-функции - в часть public, т.к. они используются в классах akt, cena, ved.

Спроектируем прототипы элементов-функций класса ind:
  • void init_ind(int,char*); - инициализирует (создает) элемент индексного массива; принимает номер записи и значение ключа записи;
  • void init_kol(int); - инициализирует кол-во элементов массива;
  • int dob_ind(char*); - поиск номера добавляемой записи; принимает значение ключа записи, возвращает номер записи файла;
  • int poisk_ind(char*,int,int&); - поиск номера искомой записи; принимает значение ключа записи, индекс элемента начала поиска; возвращает номер записи файла и соответствующий индекс элемента;
  • void cor_ind(int,char*); - корректирует элемент индексного массива; принимает индекс элемента и значение ключа записи.

//файл интерфейса класса ind-index.hpp

#ifndef index_hpp

#define index_hpp

#include

#include

#include

const int max_mass=100;

const int max_pole=10;

class ind //определение базового класса

{

private: //закрытые элементы класса

struct tip_index //индексный массив

{

char kluch[max_pole]; //ключ записи

int nomer; //номер записи в файле данных

} index[max_mass];

int kol; //кол-во элементов индексного массива

public: //защищенные элементы класса

char* imf; //имя файла данных

ind(char* im):imf(im) {kol=0;}//конструктор базового класса

void init_ind(int,char*); //инициализация элемента массива

void init_kol(int); //инициализ. количества элементов

int dob_ind(char*); //добавление нового элемента

int poisk_ind(char*,int,int&);//поиск элемента массива

void cor_ind(int,char*); //корректировка массива

};

#endif

Файлы интерфейсов производных классов


Рассмотрим производные классы akt и cena. Элементы-данные этих классов наследуются классом ved, и поэтому, поместим их в часть protected. Так как элементы-функции formecran, vvod, vyvod вызываются только функциями данного класса, разместим их в части private. Элементы-функции init, sozdanie, correct будут вызываться из файла управления через объект класса, и, согласно правилам доступа, должны быть расположены в части public. Элементы-функции zapis_zap и chtenie_zap используются функциями этих классов, а также - класса ved. Поэтому, поместим их в часть protected.

//файл интерфейса класса akt - akt.hpp

#ifndef akt_hpp

#define akt_hpp

#include

#include

#include

#include "index.hpp"

class akt : public ind //определение производного класса akt

{ //простое наследование с атрибутом public

protected: //защищенные элементы класса

char tabn[10]; //табельный номер рабочего

char fio[30]; //ф.и.о.

char vid[10]; //вид выполненной работы

float objem; //объем выполненной работы

public: //открытые элементы класса

akt(char* im):ind(im) //конструктор производного класса akt

{ //вызывает конструктор базового класса

tabn[0]='\0'; //и инициализирует собственные элементы

fio[0]='\0';

vid[0]='\0';

objem=0;

} //прототипы элементов-функций класса:

void init(); //инициализация индексного массива

void sozdanie(); //ввод новых документов и запись в файл

void correct(int); //корректировка (замена, удаление)

protected:

void zapis_zap(int); //запись записи в файл

void chtenie_zap(int);//чтение записи из файла

private: //закрытые элементы-функции класса

void formecran(char* podmenu);//вывод формы документа

void vvod(); //ввод содержимого документа

void vyvod(); //вывод содержимого документа

};

#endif

Может возникнуть вопрос - почему выбран атрибут наследования public? Если выбрать private, то элементы-функции класса ind становятся в классах akt и cena private. Доступ к ним в этих классах есть, но они становятся закрытыми для дальнейшего наследования и недоступны в классе ved. А ведь функция sozdanie класса ved, выполняющая обработку файлов, должна использовать элементы класса ind. Именно поэтому, необходимо использовать public.

//файл интерфейса класса cena - cena.hpp

#ifndef cena_hpp

#define cena_hpp

#include

#include

#include

#include "index.hpp"

class cena : public ind //определение производного класса cena

{ //простое наследование с атрибутом public

protected: //защищенные элементы класса

char vid[10]; //вид работы

char naim[30]; //наименование работы

float rascenka; //расценка работы

public: //открытые элементы класса

cena(char* im):ind(im)//конструктор

{ //вызывает конструктор базового класса

vid[0]='\0'; //и инициализирует собственные элементы

naim[0]='\0';

rascenka=0;

} //прототипы элементов-функций класса:

void init(); //инициализация индексного массива

void sozdanie(); //ввод новых документов и запись в файл

void correct(int); //корректировка (замена, удаление)

protected:

void zapis_zap(int); //запись записи в файл

void chtenie_zap(int);//чтение записи из файла

private: //закрытые элементы класса

void formecran(char* podmenu);//вывод формы документа

void vvod(); //ввод содержимого документа

void vyvod(); //вывод содержимого документа

};

#endif

Рассмотрим класс ved, являющийся производным от двух классов akt и cena. Элементы-данные класса stoim, itog и элемент-функция formecran, используемые только функциями данного класса, разместим в части private. Функция sozdanie будет вызываться из файла управления через объект класса ved, и, согласно правилам доступа, должна быть расположена в части public.

//файл интерфейса класса ved - vedom.hpp

#ifndef vedom_hpp

#define vedom_hpp

#include

#include

#include

#include

#include "akt.hpp"

#include "cena.hpp"

class ved : public akt,public cena //определение производного

{ //класса ved, множественное наследование

private: //закрытые элементы класса

float stoim; //стоимость работы

float itog; //итоговая стоимость всех работ рабочего

public: //открытые элементы класса

ved(char* im1,char* im2):akt(im1),cena(im2)//конструктор

{ //вызывает конструкторы базовых классов

stoim=itog=0; //akt и cena,иниц. собственные элементы

} //прототипы элементов-функций:

void sozdanie(); //расчет и вывод документов

private: //закрытый элемент класса

void formecran(char*);//вывод формы документа

};

#endif

Дадим объяснение тому, почему выбран атрибут наследования public? Будем вызывать в файле управления элементы-функции классов с помощью переменной obj, объекта класса ved. Если выбрать атрибут private, то объект obj будет иметь доступ только к собственным элементам из части public (функция sozdanie), а доступ к наследуемым элементам (функции init, sozdanie, correct) будет закрыт. Следовательно, выберем атрибут public.

Файл управления


Файл управления upr.cpp содержит функции main, menu и podmenu. Главная функция main вызывает элементы-функции init классов akt и cena, а затем функцию menu. Функция menu вызывает функцию podmenu и элемент-функцию sozdanie класса ved. Функция podmenu реализует две формы подменю и вызов элементов-функций sozdanie и correct классов akt и cena. Она имеет два формальных параметра, принимающие соответственно местоположение формы подменю и номер подменю, обеспечивающий вызов элементов-функций класса (akt или cena).

При доступе к элементам-функциям через объект производного класса ved возникает неоднозначность множественного наследования, связанная с тем, что в базовых классах akt и cena имеются элементы с одинаковыми именами (sozdanie, correct). Для разрешения неоднозначности используем имена базовых классов с операцией разрешения видимости (например, obj.akt::init(); ).

//файл управления upr.cpp

#include "vedom.hpp"

char imf_akt[13]; //для хранения имени файла данных Акты

char imf_cena[13]; //для хранения имени файла данных Расценки

ved obj(imf_akt,imf_cena);//объявление объекта класса ved

void podmenu(int n,int x) //функция подменю

{ //n – номер подменю (0-akt,1-cena), x - номер колонки вывода подменю

char ch;

char *m[]={" Ввод ",

" Поиск ",

" Замена ",

" Удаление ",

" Выход "

};

int pos[5];

_setcursortype(_NOCURSOR);

gotoxy(2,23);

clreol();

cputs("Выберите пункт меню и нажмите ");

for (int k=0;k<5;k++)

{ if (k==0)

textattr(0+(2<<4));

else

textattr(0+(7<<4));

gotoxy(x,3+k);

pos[k]=wherey();

cputs(m[k]);

}

k=0;

for (;;)

{ ch=getch();

if (ch==13) break;

if (ch==0)

{ ch=getch();

switch (ch)

{ case 80: if (k==4) continue;

gotoxy(x,pos[k]);

textattr(0+(7<<4));

cputs(m[k]);

k++;

gotoxy(x,pos[k]);

textattr(0+(2<<4));

cputs(m[k]);

textattr(15+(0<<4));

break;

case 72: if (k==0) continue;

gotoxy(x,pos[k]);

textattr(0+(7<<4));

cputs(m[k]);

k--;

gotoxy(x,pos[k]);

textattr(0+(2<<4));

cputs(m[k]);

textattr(15+(0<<4));

break;

}

}

}

textattr(15+(0<<4));

_setcursortype(_NORMALCURSOR);

switch (k)

{ case 0: if (n==0) obj.akt::sozdanie(); //вызов функ. кл. akt

if (n==1) obj.cena::sozdanie();//вызов функ. кл.cena

break;

case 1:

case 2:

case 3: if (n==0) obj.akt::correct(k); //вызов функ. кл. akt

if (n==1) obj.cena::correct(k);//вызов функ. кл.cena

break;

case 4: break;

}

if (k!=4) podmenu(n,x); //рекурсивный вызов функции

}

void menu() // функция menu

{ char ch;

char *m[]={ " Акты работ ",

" Расценки работ ",

" Ведомость ",

" Выход "

};

int pos[4];

clrscr();

_setcursortype(_NOCURSOR);

gotoxy(2,23);

cputs("Выберите пункт меню (-> и <-) и нажмите ");

gotoxy(16,1);

for (int k=0;k<4;k++)

{ if (k==0)

textattr(0+(2<<4));

else

textattr(0+(7<<4));

pos[k]=wherex();

cputs(m[k]);

}

k=0;

for (;;)

{ ch=getch();

if (ch==13) break;

if (ch==0 && kbhit())

{

ch=getch();

switch (ch)

{ case 77: if (k==3) continue;

gotoxy(pos[k],1);

textattr(0+(7<<4));

cputs(m[k]);

k++;

gotoxy(pos[k],1);

textattr(0+(2<<4));

cputs(m[k]);

textattr(15+(0<<4));

break;

case 75: if (k==0) continue;

gotoxy(pos[k],1);

textattr(0+(7<<4));

cputs(m[k]);

k--;

gotoxy(pos[k],1);

textattr(0+(2<<4));

cputs(m[k]);

textattr(15+(0<<4));

break;

}

}

}

textattr(15+(0<<4));

_setcursortype(_NORMALCURSOR);

switch (k)

{

case 0:

case 1: podmenu(k,pos[k]);//вызов внешней функции

break;

case 2: obj.sozdanie(); //вызов элемент-функции класса ved

break; //операция (::) не требуется

case 3: break;

}

if (k!=3) menu();

}

main() //функция main

{ clrscr();

gotoxy(2,23);

cout<<"Введите имя файла Акты:";

cin>>imf_akt;

gotoxy(2,23);

clreol();

cout<<"Введите имя файла Расценки:";

cin>>imf_cena;

obj.akt::init(); //вызов элемент-функции класса akt

obj.cena::init(); //вызов элемент-функции класса cena

menu(); //вызов внешней функции

}