Лекция №
Вид материала | Лекция |
3.3Проектирование файлов интерфейсов классов. Лекция № 13. Файлы интерфейсов производных классов Файл управления |
- «Социальная стратификация и социальная мобильность», 46.19kb.
- Первая лекция. Введение 6 Вторая лекция, 30.95kb.
- Лекция Сионизм в оценке Торы Лекция Государство Израиль испытание на прочность, 2876.59kb.
- Текст лекций н. О. Воскресенская Оглавление Лекция 1: Введение в дисциплину. Предмет, 1185.25kb.
- Собрание 8-511 13. 20 Лекция 2ч режимы работы эл оборудования Пушков ап 8-511 (ррэо), 73.36kb.
- Концепция тренажера уровня установки. Требования к тренажеру (лекция 3, стр. 2-5), 34.9kb.
- Лекция по физической культуре (15. 02.; 22. 02; 01. 03), Лекция по современным технологиям, 31.38kb.
- Тема Лекция, 34.13kb.
- Лекция посвящена определению термина «транскриптом», 219.05kb.
- А. И. Мицкевич Догматика Оглавление Введение Лекция, 2083.65kb.
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(); //вызов внешней функции
}