
- •1.1 Введение
- •1.2 Парадигмы программирования
- •1.2.1 Процедурное программирование
- •Void f ()
- •1.2.5 Объектно-ориентированное программирование
- •1.5.1 Механизм вызова
- •Virtual void rotate ( int );
- •1.5.3 Множественное наследование
- •1.6 Пределы совершенства
- •2.2 Имена
- •2.3.2 Неявное преобразование типа
- •2.4 Литералы
- •2.4.4 Строки
- •2.6. Экономия памяти
- •2.6.1 Поля
- •3.1.1 Анализатор
- •3.1.2 Функция ввода
- •Int main(int argc, char* argv[])
- •3.2 Сводка операций
- •3.2.3 Инкремент и декремент
- •3.2.5 Преобразование типа
- •3.2.6 Свободная память
- •Void generate(enode* n)
- •3.3.2 Оператор goto
- •4.1 Введение
- •4.3.1 Единственный заголовочный файл
- •Inline name* insert(const char* s) { return look(s,1); }
- •Int main(int argc, char* argv[]) { /* ... */ }
- •4.3.2 Множественные заголовочные файлы
- •Int main(int argc, char* argv[]) { /* ... */ }
- •4.4 Связывание с программами на других языках
- •4.6.3 Передача параметров
- •Inline. Удалите из файлов .C все описания внешних, а определения
- •5.1 Введение и краткий обзор
- •Int month, day, year;
- •Int month, day, year;
- •5.3.1 Альтернативные реализации
- •5.3.2 Законченный пример класса
- •Void task::shedule(int p) { /* ... */ }
- •5.5.3 Свободная память
- •Int no_of_members;
- •Int no_of_members;
- •5.5.5 Массивы объектов класса
- •6.1 Введение и краткий обзор
- •Void f()
- •Void g()
- •6.2.3 Иерархия классов
- •6.2.4 Поля типа
- •6.4.1 Монитор экрана
- •6.5 Множественное наследование
- •7.1 Введение
- •7.3 Пользовательские операции преобразования типа
- •7.3.2 Операции преобразования
- •7.3.3 Неоднозначности
- •7.5 Большие объекты
- •Inv() обращает саму матрицу m, а не возвращает новую, обратную m,
- •7.13 Предостережения
- •8.1 Введение
- •8.4.5 Введение операций с помощью параметров шаблонного класса
- •8.7.1 Задание реализации с помощью параметров шаблона
- •Void some_function()
- •V value;
- •9.1 Обработка ошибок
- •9.1.2 Другие точки зрения на особые ситуации
- •9.3.2 Производные особые ситуации
- •X(const char* X, const char* y)
- •9.4.2 Предостережения
- •9.4.3 Исчерпание ресурса
- •10.1 Введение
- •10.2 Вывод: То, что для прикладной программы представляется выводом,
- •10.2 Вывод
- •10.2.1 Вывод встроенных типов
- •10.4.1.2 Поля вывода
- •10.4.1.4 Вывод целых
- •10.5.1 Закрытие потоков
- •10.5.2 Строковые потоки
- •Int printf(const char* format, ...)
- •X Целый параметр выдается в шестнадцатеричной записи;
- •11.1 Введение
- •11.2 Цели и средства
- •11.3 Процесс развития
- •11.3.1 Цикл развития
- •11.3.2 Цели проектирования
- •11.3.3 Шаги проектирования
- •11.3.3.1 Шаг 1: определение классов
- •11.3.3.2 Шаг 2: определение набора операций
- •11.3.3.3 Шаг 3: указание зависимостей
- •11.3.3.4 Шаг 4: определение интерфейсов
- •11.3.3.5 Перестройка иерархии классов
- •11.3.3.6 Использование моделей
- •11.3.4 Эксперимент и анализ
- •11.3.5 Тестирование
- •11.3.6 Сопровождение
- •11.3.7 Эффективность
- •11.4 Управление проектом
- •11.4.1 Повторное использование
- •11.4.2 Размер
- •11.4.3 Человеческий фактор
- •11.5 Свод правил
- •11.6 Список литературы с комментариями
- •12.1 Проектирование и язык программирования.
- •12.1.1 Игнорирование классов
- •12.1.2 Игнорирование наследования
- •12.1.3 Игнорирование статического контроля типов
- •12.1.4 Гибридный проект
- •12.2.1 Что представляют классы?
- •12.2.2 Иерархии классов
- •Void f(Vehicle* p)
- •12.2.3 Зависимости в рамках иерархии классов.
- •Void f()
- •Void q(cfield* p)
- •12.2.6 Отношения использования
- •12.2.7 Отношения внутри класса
- •Void f(Rational r, Big_int I)
- •12.3 Компоненты
- •12.4 Интерфейсы и реализации
- •12.5 Свод правил
- •13.1 Введение
- •13.2 Конкретные типы
- •13.5.1 Информация о типе
- •13.6 Обширный интерфейс
- •Void put(const t*);
- •13.7 Каркас области приложения
- •13.8 Интерфейсные классы
- •13.10 Управление памятью
13.7 Каркас области приложения
Мы перечислили виды классов, из которых можно создать библиотеки, нацеленные на проектирование и повторное использование прикладных программ. Они предоставляют определенные "строительные блоки" и объясняют как из них строить. Разработчик прикладного обеспечения создает каркас, в который должны вписаться универсальные строительные блоки. Задача проектирования прикладных программ может иметь иное, более обязывающее решение: написать программу, которая сама будет создавать общий каркас области приложения. Разработчик прикладного обеспечения в качестве строительных блоков будет встраивать в этот каркас прикладные программы. Классы, которые образуют каркас области приложения, имеют настолько обширный интерфейс, что их трудно назвать типами в обычном смысле слова. Они приближаются к тому пределу, когда становятся чисто прикладными классами, но при этом в них фактически есть только описания, а все действия задаются функциями, написанными прикладными программистами.
Для примера рассмотрим фильтр, т.е. программу, которая может выполнять следующие действия: читать входной поток, производить над ним некоторые операции, выдавать выходной поток и определять конечный результат. Примитивный каркас для фильтра будет состоять из определения множества операций, которые должен реализовать прикладной программист:
class filter {
public:
class Retry {
public:
virtual const char* message() { return 0; }
};
virtual void start() { }
virtual int retry() { return 2; }
virtual int read() = 0;
virtual void write() { }
virtual void compute() { }
virtual int result() = 0;
};
Нужные для производных классов функции описаны как чистые виртуальные, остальные функции просто пустые. Каркас содержит основной цикл обработки и зачаточные средства обработки ошибок:
int main_loop(filter* p)
{
for (;;) {
try {
p->start();
while (p->read()) {
p->compute();
p->write();
}
return p->result();
}
catch (filter::Retry& m) {
cout << m.message() << '\n';
int i = p->retry();
if (i) return i;
}
catch (...) {
cout << "Fatal filter error\n";
return 1;
}
}
}
Теперь прикладную программу можно написать так:
class myfilter : public filter {
istream& is;
ostream& os;
char c;
int nchar;
public:
int read() { is.get(c); return is.good(); }
void compute() { nchar++; };
int result()
{ os << nchar
<< "characters read\n";
return 0;
}
myfilter(istream& ii, ostream& oo)
: is(ii), os(oo), nchar(0) { }
};
и вызывать ее следующим образом:
int main()
{
myfilter f(cin,cout);
return main_loop(&f);
}
Настоящий каркас, чтобы рассчитывать на применение в реальных задачах, должен создавать более развитые структуры и предоставлять больше полезных функций, чем в нашем простом примере. Как правило, каркас образует дерево узловых классов. Прикладной программист поставляет только классы, служащие листьями в этом многоуровневом дереве, благодаря чему достигается общность между различными прикладными программами и упрощается повторное использование полезных функций, предоставляемых каркасом. Созданию каркаса могут способствовать библиотеки, в которых определяются некоторые полезные классы, например, такие как scrollbar ($$12.2.5) и dialog_box ($$13.4). После определения своих прикладных классов программист может использовать эти классы.