Лекции.ИНФО


Текущую позицию каждого файлового указателя можно определить с помощью этих двух функций.



pos_type tellg();

pos_type tellp();

Здесь используется тип pos_type (он определен в классе ios), позволяющий хранить самое большое значение, которое может возвратить любая из этих функций.

Существуют перегруженные версии функций seekg() и seekp(), которые перемещают файловые указатели в позиции, заданные значениями, возвращаемыми функциями tellg() и tellp() соответственно. Вот как выглядят их прототипы,

istream &seekg(pos_type position);

ostream &seekp(pos_type position);

Проверка статуса ввода-вывода

С++-система ввода-вывода поддерживает статусную информацию о результатах выполнения каждой операции ввода-вывода. Текущий статус потока ввода-вывода описывается в объекте типа iostate, который представляет собой перечисление (оно определено в классе ios), включающее следующие члены.

Статусную информацию о результате выполнения операций ввода-вывода можно получать двумя способами. Во-первых, можно вызвать функцию rdstate(), которая является членом класса ios. Она имеет такой прототип.

iostate rdstate();

Функция rdstate() возвращает текущий статус флагов ошибок. Нетрудно догадаться, что, судя по приведенному выше списку флагов, функция rdstate() возвратит значение goodbit при отсутствии каких бы то ни было ошибок. В противном случае она возвращает соответствующий флаг ошибки.

Во-вторых, о наличии ошибки можно узнать с помощью одной или нескольких следующих функций-членов класса ios.

bool bad();

bool eof();

bool fail();

bool good();

Функция eof() рассматривалась выше. Функция bad() возвращает значение ИСТИНА, если в результате выполнения операции ввода-вывода был установлен флаг badbit. Функция fail() возвращает значение ИСТИНА, если в результате выполнения операции ввода-вывода был установлен флаг failbit. Функция good() возвращает значение ИСТИНА, если при выполнении операции ввода-вывода ошибок не произошло. В противном случае они возвращают значение ЛОЖЬ.

Если при выполнении операции ввода-вывода произошла ошибка, то, возможно, прежде чем продолжать выполнение программы, имеет смысл сбросить флаги ошибок. Для этого используйте функцию clear() (член класса ios), прототип которой выглядит так.

void clear (iostate flags = ios::goodbit);

Если параметр flags равен значению goodbit (оно устанавливается по умолчанию), все флаги ошибок очищаются. В противном случае флаги устанавливаются в соответствии с заданным вами значением.

Прежде чем переходить к следующему разделу, стоит опробовать функции, которые сообщают данные о состоянии флагов ошибок, внеся в предыдущие примеры программ код проверки ошибок.

Использование перегруженных операторов ввода-вывода при работе с файлами

Выше в этой главе вы узнали, как перегружать операторы ввода и вывода для собственных классов, а также как создавать собственные манипуляторы. В приведенных выше примерах программ выполнялись только операции консольного ввода-вывода. Но поскольку все С++-потоки одинаковы, одну и ту же перегруженную функцию вывода данных, например, можно использовать для вывода информации как на экран, так и в файл, не внося при этом никаких существенных изменений. Именно в этом и заключаются основные достоинства С++-системы ввода-вывода.

В следующей программе используется перегруженный (для класса three_d) оператор вывода для записи значений координат в файл threed.

/* Использование перегруженного оператора ввода-вывода для записи объектов класса three_d в файл.

*/

#include <iostream>

#include <fstream>

using namespace std;

class three_d {

  int x, y, z; // 3-мерные координаты; они теперь закрыты

 public:

  three_d(int a, int b, int с) { x = a; у = b; z = c; }

  friend ostream &operator<<(ostream &stream, three_d obj); /* Отображение координат X, Y, Z (оператор вывода для класса three_d). */

};

ostream &operator<<(ostream &stream, three_d obj)

{

 stream << obj.x << ", ";

 stream << obj.у << ", ";

 stream << obj.z << "";

 return stream; // возвращает поток

}

Int main()

{

 three_d a(1, 2, 3), b(3, 4, 5), c(5, 6, 7);

 ofstream out("threed");

 if(!out) {

  cout << "He удается открыть файл.";

  return 1;

 }

 out << a << b << c;

 out.close();

 return 0;

}

Если сравнить эту версию операторной функции вывода данных для класса three_d с той, что была представлена в начале этой главы, можно убедиться в том, что для "настройки" ее на работу с дисковыми файлами никаких изменений вносить не пришлось. Если операторы ввода и вывода определены корректно, они будут успешно работать с любым потоком.

Важно! Прежде чем переходить к следующей главе, не пожалейте времени и поработайте с С++-функциями ввода-вывода. Создайте собственный класс, а затем определите для него операторы ввода и вывода. А еще создайте собственные манипуляторы.


Глава 19: Динамическая идентификация типов и операторы приведения типа

В этой главе рассматриваются два средства C++, которые поддерживают современное объектно-ориентированное программирование: динамическая идентификация типов (run-time type identification - RTTI) и набор дополнительных операторов приведения типа. Ни одно из этих средств не было частью оригинальной спецификации C++, но оба они были добавлены с целью усиления поддержки полиморфизма времени выполнения. Под RTTI понимается возможность проведения идентификации типа объекта во время выполнения программы. Рассматриваемые здесь операторы приведения типа предлагают программисту более безопасные способы выполнения этой операции. Как будет показано ниже, один из них, dynamic_cast, непосредственно связан с RTTI-идентификацией, поэтому операторы приведения типа и RTTI имеет смысл рассматривать в одной главе.

Динамическая идентификация типов (RTTI)

С динамической идентификацией типов вы, возможно, незнакомы, поскольку это средство отсутствует в таких неполиморфных языках, как С. В неполиморфных языках попросту нет необходимости в получении информации о типе во время выполнения программы, так как тип каждого объекта известен во время компиляции (т.е. еще при написании программы). Но в таких полиморфных языках, как C++, возможны ситуации, в которых тип объекта неизвестен в период компиляции, поскольку точная природа этого объекта не будет определена до тех пор, пока программа на начнет выполняться. Как вы знаете, C++ реализует полиморфизм посредством использования иерархии классов, виртуальных функций и указателей на базовые классы. Указатель на базовый класс можно использовать для ссылки на члены как этого базового класса, так и на члены любого объекта, выведенного из него. Следовательно, не всегда заранее известно, на объект какого типа будет ссылаться указатель на базовый класс в произвольный момент времени. Это выяснится только при выполнении программы — при использовании одного из средств динамической идентификации типов.

Для получения типа объекта во время выполнения программы используйте оператор typeid.

Чтобы получить тип объекта во время выполнения программы, используйте оператор typeid. Для этого необходимо включить в программу заголовок <typeinfo>. Самый распространенный формат использования оператора typeid таков.

Typeid(object)

Здесь элемент object означает объект, тип которого нужно получить. Можно запрашивать не только встроенный тип, но и тип класса, созданного программистом. Оператор typeid возвращает ссылку на объект типа type_infо, который описывает тип объекта object.

В классе type_info определены следующие public-члены.

bool operator = (const type_info &ob);

bool operator !=(const type_info &ob);

bool before(const type_info &ob);

const char *name();

Перегруженные операторы "==" и "!=" служат для сравнения типов. Функция before() возвращает значение true, если вызывающий объект в порядке сопоставления стоит перед объектом (элементом ob), используемым в качестве параметра. (Эта функция предназначена в основном для внутреннего использования. Возвращаемое ею значение результата не имеет ничего общего с наследованием или иерархией классов.) Функция name() возвращает указатель на имя типа.

Рассмотрим простой пример использования оператора typeid.

// Пример использования оператора typeid.

#include <iostream>

#include <typeinfo>

using namespace std;

class myclass {

 // . . .

};

Int main()

{

 int i, j;

 float f;

 myclass ob;

 cout << "Тип переменной i: " << typeid(i).name();

 cout << endl;

 cout << "Тип переменной f: " << typeid(f).name();

 cout << endl;

 cout << "Тип переменной ob: " << typeid(ob).name();

 cout << "";

 if(typeid(i) == typeid(j))

  cout << "Типы переменных i и j одинаковы.";

 if(typeid(i) != typeid(f))

  cout << "Типы переменных i и f неодинаковы.";

 return 0;

}









Читайте также:

  1. III. Узлы для связывания двух тросов
  2. SWOT-анализ: характеристики при оценке сильных и слабых сторон компании, ее возможностей и угроз ей
  3. VI. Определение девиации по сличению показаний двух компасов
  4. А можно ли сказать, что Природа есть нечто определенное?
  5. А. Можно разделить и молекулу, и атом. Б. Можно разделить молекулу, невозможно разделить атом. В. Можно разделить атом, невозможно разделить молекулу. Г. Невозможно разделить ни молекулу, ни атом.
  6. А. Переносом стальных опилок. Б. Переносом магнита. В. Переносом проводника с током. Г. Вытягиванием его с помощью сильного электромагнита. Д. Магнитное поле переместить невозможно.
  7. А. Построение кривой производственных возможностей
  8. А.1. Двух- и многосторонняя облигаторная унификация
  9. Аграрное развитие России на рубеже двух веков.
  10. Алгоритмы записи произвольной функции, заданной в таблице в виде с помощью элементарных функций.
  11. Анализ производительности с помощью анализа последовательности событий
  12. Анатомо-морфологическая база высших психических функций.


Последнее изменение этой страницы: 2016-03-17; Просмотров: 103;


lektsia.info 2017 год. Все права принадлежат их авторам! Главная