Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Cpp_Страуструп.doc
Скачиваний:
17
Добавлен:
03.05.2015
Размер:
3.2 Mб
Скачать

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). После определения

своих прикладных классов программист может использовать эти классы.