- •Раздел 4. Разработка по Тема 4.1. Проектирование интерфейса с пользователем
- •4.1.1. Типы пользовательских интерфейсов.
- •4.1.2. Пользовательская и программная модели интерфейса.
- •4.1.3. Разработка диалогов.
- •4.1.4. Основные компоненты графических пользовательских интерфейсов.
- •Тема 4.2. Реализация графических пользовательских интерфейсов.
- •4.2.1. Диалоги, управляемые пользователем.
- •4.2.2. Диалоги, управляемые системой.
- •4.2.3. Использование метафор.
- •4.2.4. Технология Drag and Drop.
- •4.2.5. Интеллектуальные элементы.
- •4.3.1. Базовые типы данных.
- •Константы
- •Область действия имен
- •4.3.2. Указатели и адресная арифметика.
- •4.3.3. Составные типы данных. Структуры
- •Битовые поля
- •Определение типов
- •Перечислимые типы
- •4.3.4. Выражения и операции.
- •4.3.5. Управляющие конструкции. Условные операторы
- •Операторы циклов
- •4.4.1. Статические одномерные массивы.
- •4.4.2. Статические многомерные массивы.
- •4.4.3. Динамические массивы.
- •4.4.4. Массивы указателей.
- •4.5.1. Стеки.
- •4.5.2. Очереди.
- •4.5.3. Списки.
- •4.5.4. Бинарные деревья.
- •4.6.1. Объявление классов и экземпляров классов.
- •4.6.2. Инкапсуляция данных и методов.
- •4.6.3. Конструкторы классов.
- •Конструктор по умолчанию
- •Конструктор копирования
- •4.6.4. Деструкторы классов.
- •4.7.1. Разделы в описании класса.
- •4.7.2. Friend-конструкции.
- •4.7.3. Статические члены классов.
- •4.7.4. Использование описателя const в классах.
- •4.8.1. Вложенность классов.
- •4.8.2. Наследование данных и методов.
- •4.8.3. Типы наследования.
- •4.9.1. Полиморфизм раннего связывания.
- •4.9.2. Полиморфизм позднего связывания и виртуальные функции.
- •4.9.3. Абстрактные методы и классы.
- •4.10.1. Функции консольного ввода-вывода.
- •4.10.2. Функции файлового ввода-вывода.
- •4.10.3. Использование библиотеки классов потокового ввода-вывода.
- •4.11.1. Перегрузка операций.
- •4.11.2. Шаблоны функций.
- •4.11.3. Шаблоны классов.
- •4.11.4. Обработка исключений.
- •Тема 4.12. Com-технология.
- •4.12.1. Основные понятия.
- •4.12.2. Типы интерфейсов.
- •Свойства интерфейсов
- •Типы интерфейсов
- •4.12.3. Типы com-объектов.
- •4.12.4. Фабрика классов.
- •Тема 4.13. Построение com-сервера.
- •4.13.1. Язык idl.
- •Содержимое файла idl
- •4.13.2. Определение пользовательского интерфейса.
- •4.13.3. Реализация пользовательского интерфейса.
- •4.13.4. Создание тестового клиента.
- •Тема 4.14. Обзор платформы ms .Net.
- •4.14.1. Общая идея архитектуры .Net.
- •4.14.2. Достоинства и недостатки .Net.
- •4.14.3. Схема трансляции программ в .Net.
- •4.14.4. Язык msil.
- •4.14.5. Объектно-ориентированная модель .Net.
4.10.3. Использование библиотеки классов потокового ввода-вывода.
В языке C++, так же, как и в С, не предусмотрены какие-либо встроенные функции или операторы ввода-вывода. Эти действия осуществляются с помощью функций внешних библиотек, определенных в файлах заголовков, таких как stdio.h, stdiostr.h, iostream.h и других. Процедуры ввода-вывода библиотеки, на которую ссылается iostream.h, осуществляют преобразование значений переменные стандартных типов, таких как int или double, в последовательность символов, и наоборот. В библиотеке описан класс iostream, в котором операция << переопределена так, чтобы вывод в поток данных всех стандартных типов языка C++ был максимально простым и удобным. Операция >> переопределена в классе istream для ввода данных стандартных типов. Для ввода и вывода внутренних данных классов, определенных пользователем, операции >> и << должны быть переопределены в этих классах.
В библиотеке определен объект cout класса ostream, который связан ее стандартным потоком вывода и является аналогом потока stdout в библиотеке stdio.h. Объект сеrr -поток вывода сообщений об ошибках ввода-вывода, clog — поток вывода сообщений пользователю. Объект cin класса istream обозначает стандартный поток ввода.
Оператор cout<<i; интерпретируется как cout.operator<<(i);. Так как тип возвращаемого значения операции - ostream&, то возможна цепочка последовательного вывода. Оператор cout<<I<<j; интерпретируется как (cout.operator<<(i)).operator<<(j);.
#include <iostream>
using namespace std;
class Man // Класс объектов
{
private: // Секция закрытого доступа
char Name[20];
unsigned int Age; // Скрытые внутренние данные
public: // Секция открытого доступа
void in ()// Метод класса
// Здесь те же коды, что и ранее
{ // Метод (функция) ввода
cout<<"Type Man"<<endl<<"Name: ";
cin>>Name;
// Name = strcpy(new char[strlen(buff)+1], buff);
cout<<" Age: ";
cin>>Age;
}
void out ()
{ // Метод класса
cout<<Name<<" "<<Age;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int i;
//==Демонстрация использования класса ====//
Man m; // Объект m класса Man
m.in(); m.out (); // Ввод, вывод данных
//m.Age = -2000; //Этот оператор ошибочен и ошибка
// выявляется на стадии компиляции
cin>>i;
return 0;
}
void main() //Подключите iostream.h
{
char с = 'С', str[80];
int i = -32767;
float v = 2.99792e8, t=3, s=0.;
double perm=12.5664E-7;
//= = = = = = = Вывод в поток cout = = = ====//
cout <<\n i=" << i;
cout << "\n c=" << c;
cout << "\n s+vt= " << (s+v*t) << " m" << "\n Open space permiability = "<<perm; cout << "\nEnter fn integer : "; cin >> i; cout << "\nA real : "; cin >> s: cout << "\nA string of chars: ": cin >> str; cout << "\nYou entered: "<<i<<' '<<s<<' '<<str<<endl;
}
Результат работы этой программы:
i=-32768
с=С
s+vt= 8.99376e+08 m
Open space permiability = 1.25664e-06 и т.д.
Пример иллюстрирует использование операций >> и << для ввода и вывода стандартных типов. Для ввода и вывода переменных нестандартных типов, например, объектов класса Vector, операции << и >> следует переопределить в классе Vector. С этой целью дополним класс описанием friend-функций и реализуем их тела вне блока описания:
friend ostream& operator<<(ostream&, Vector& v);
friend istream& operator>>(istream&, Vector& v);
ostream& operator<<(ostream& os, Vector& v)
{return os<<"\n Vector: xl="<<v.xl<<" x2="<<v.x2;}
istreams operator>>(istream& is, Vector& v)
{
double dl, d2;
cout << "\n xl= "; is » dl;
cout << " x2= "; is » d2;
v=Vector (dl, d2); // Создание объекта
return is; // Входной поток
}
Первый формальный параметр (&os) функции operator<< — ссылка на объект класса ostream. С ним связан стандартный поток cout. Второй параметр является ссылкой на объект класса Vector. Функция возвращает адрес выходного потока. Аналогичный комментарий можно дать и для переопределенной операции ввода. Теперь можно вводить и выводить объекты класса Vector. Добавьте в функцию следующий код для проверки изменений:
Vector х, у; //Переопределенные операции ввода-вывода cout << "\n\n Enter vector:"; cin >> x; cout << "\n Enter one more:"; cin >> y; cout << "\n\n You have entered: " << x <<y; cout << "\n The norm of |x+y|="<< !(x+y) << "\n\n";
В целом библиотека потоковых классов C++ состоит из многих классов, объединенных в два иерархических дерева. Класс streambuf является базовым классом для классов filebuf, stdiobuf и strstreambuf, обеспечивающих буферизованный интерфейс между данными пользователя и такими областями хранения данных, как память или физическое устройство. Более 30 методов класса streambuf позволяют выбирать символы из буфера, помещать их туда, позиционировать указатель, запрашивать количество оставшихся символов в буфере и т. п. Методы производных классов (само определение производного класса будет дано в следующем разделе) позволяют открывать и закрывать файлы, манипулировать дескриптором файла, управлять вводом-выводом на консоль, создавать буфер для форматирования строки символов в памяти. Второй базовый класс ios порождает дерево классов istream, ostream, iostream. Каждый из этих классов, в свою очередь, имеет несколько производных классов. В результате дерево состоит из более чем 10 классов, методы которых дают возможность производить ввод-вывод с использованием операций форматирования высокого уровня. Подробное описание этих многочисленных функций невозможно дать в объеме лекций, поэтому рассмотрим лишь один пример использования некоторых из классов библиотеки:
void main()
{
int с;
const char *fn = "test.txt";
ofstream fOut: // Объявление выходного потока
streambuf *bufOut, *bufln = cin.rdbufO;
// Открыть файл, встать в конец, разрешить дозапись
fOut.open (fn, ios::ate | ios::app);
if (IfOut) cerr « "Can't open " « fn: exit(-l);
bufOut = fOut. rdbuf (); // Связывание of stream и streambuf
clog«"Enter some text (AZ - to stop)"«endl;
// Ввод с клавиатуры, вывод на экран и в файл
while ((c=bufln->sbumpc()) != EOF)
{
cout « char (с); //Эхо на экран
if (bufOut->sputc(c) == EOF) cerr « "Output error";
}
fOut.close();
// Позиционирование во входном потоке
int Size = 0;
// Объявление входного потока и попытка его открытия
ifstream fin (fn, ios::in | ios::nocreate);
fin. seekg (OL.ios:: end); // Переместиться в конец файла
if ((Size = fln.tellg()) < 0)
{
сегг « fn « " not found"; exit(-l);
}
cout«fn«" Size = "«Size«endl;
}
Сначала в примере создается файл test.txt, в который вводится фрагмент текста. Класс ofstream происходит от класса ostream (смысл выражения «происходит от классов» прояснится в следующем разделе). Следующая строка программы streambuf *bufOut, *bufln = cin.rdbuf();: определяет два указателя на класс streambuf, которые используются для управления буферами потоков вывода и ввода. Метод cin.rdbuf() возвращает текущее значение указателя в потоке ввода, связанном с клавиатурой. Оператор
fOut.open (fn, ios::ate | ios::app);
обращается к методу open класса ofstream, который открывает файл с именем, переданным первым параметром в режиме, заданном вторым параметром. Второй параметр является выражением, операнды (ate и арр) которого определены в классе ios. Они являются элементами перечисления enum openjnode и допускают выполнение логических операций над собой с целью задания набора битовых признаков режима открытия файла. В нашем случае объединяются признаки арр (разрешение добавлять в конец файла) и ate (режим перемещения в конец файла при его открытии). Операция ! переопределена так, что нулевой код возврата свидетельствует об ошибке при открытии файла. Сообщение об ошибке выводится в поток сегг, который обычно направлен на экран монитора. Оператор bufOut = fOut.rdbuf(); связывает буфер вывода с выходным потоком, так как метод rdbuf класса ofstream возвращает текущее значение указателя потока (файла), которое присваивается указателю bufOut типа streambuf*.
В цикле while осуществляется последовательный ввод символов из входного потока, вывод их сначала на экран cout«char(c);, затем в буфер, связанный с файлом. Метод sbumpc класса streambuf возвращает текущий символ буфера ввода и сдвигает указатель буфера на следующий символ. Аналогичным образом метод sputc помещает символ в буфер вывода. Символ Ctrl+z служит признаком конца файла (EOF — End Of File). Чтобы закончить ввод с клавиатуры, необходимо ввести такую последовательность: Enter, ^Z, Enter. Следующая часть программы иллюстрирует, как можно позиционировать указатель в файле. Указатель переводится в конец созданного файла, и выясняется его позиция относительно начала файла. Таким образом определяется размер файла в байтах. Класс ifstream происходит от классов istream. Наличие двух аргументов при объявлении объекта заставляет выбрать один из конструкторов класса ifstream, который сразу открывает файл с именем, переданным первым параметром, и в режиме, задаваемом вторым параметром. Режим задан в виде выражения ios::in | ios: :nocreate. Результатом побитовой операции ИЛИ является установка двух признаков — открыть файл для ввода и не создавать файл, если он не существует. Позиционирование в файле осуществляется с помощью функции seekg, которая определена в классе istream и наследуется классом ifstream. Результатом вызова будет перемещение указателя потока в конец файла. Метод tellg класса istream возвращает значение текущей позиции потока, которое численно на единицу меньше размера файла в байтах.
Тема 4.11. Методы повышения гибкости и надежности объектно-ориентированных программ в Visual C++.