KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Стенли Липпман - Язык программирования C++. Пятое издание

Стенли Липпман - Язык программирования C++. Пятое издание

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн "Стенли Липпман - Язык программирования C++. Пятое издание". Жанр: Программирование издательство -, год -.
Перейти на страницу:

Для битовых полей обычно лучше подходит беззнаковый тип. Поведение битовых полей, хранимых в переменной знакового типа, определяет конкретная реализация.

Использование битовых полей

К битовым полям обращаются так же, как и к другим переменным-членам класса:

void File::write() {

 modified = 1;

 // ...

}

void File::close() {

 if (modified)

  // ... сохранить содержимое

}

Для манипулирования битовыми полями с несколькими битами обычно используют встроенные побитовые операторы (см. раздел 4.8):

File &File::open(File::modes m) {

 mode |= READ; // установить бит READ по умолчанию

 // другая обработка

 if (m & WRITE) // если открыто для чтения и записи

  // процесс открытия файла в режиме чтения/записи

 return *this;

}

Классы, определяющие члены битовых полей, обычно определяют также набор встраиваемых функций-членов для проверки и установки значений битовых полей:

inline bool File::isRead() const { return mode & READ; }

inline void File::setWrite() { mode |= WRITE; }

19.8.2. Спецификатор volatile

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

Программы, которым приходится работать непосредственно с аппаратными средствами, зачастую имеют элементы данных, значением которых управляют процессы, не контролируемые самой программой. Например, программа могла бы содержать переменную, значение которой изменяет системный таймер. Такой объект должен быть объявлен со спецификатором volatile, тогда его значение может быть изменено способами, не контролируемыми или не обнаруживаемыми компилятором. Ключевое слово volatile — это приказ компилятору не выполнять оптимизацию для таких объектов.

Спецификатор volatile используется аналогично спецификатору const, т.е. как дополнительный модификатор типа:

volatile int display_register; // значение int может измениться

volatile Task *curr_task;   // curr_task указывает на объект volatile

volatile int iax[max_size]; // каждый элемент в iax volatile volatile

Screen bitmapBuf;           // каждый член bitmapBuf volatile

Между спецификаторами типа const и volatile нет никакой взаимосвязи. Тип может быть и const, и volatile, тогда у него есть оба качества.

Точно так же класс может определить константные функции-члены, а может и асинхронно-изменяемые (volatile). Только асинхронно-изменяемые функции-члены могут быть вызваны асинхронно-изменяемым (volatile) объектом.

Взаимодействие указателей со спецификатором const описано в разделе 2.4.2. Аналогичное взаимодействие существует между указателями и спецификатором volatile. Можно объявлять асинхронно-изменяемые указатели на объекты, указатели на асинхронно-изменяемые объекты и асинхронно-изменяемые указатели на асинхронно-изменяемые объекты.

volatile int v;    // v - асинхронно-изменяемый объект типа int

int *volatile vip; // vip - асинхронно-изменяемый указатель на тип int

volatile int *ivp; // ivp - указатель на асинхронно-изменяемый тип int

// vivp - асинхронно-изменяемый указатель на асинхронно-изменяемый

// объект типа int

volatile int *volatile vivp;

int *ip = &v; // ошибка: нужен указатель на volatile

*ivp = &v;    // ok: ivp - указатель на volatile

vivp = &v;    // ok: vivp - volatile указатель на volatile

Подобно константам, адрес асинхронно-изменяемого объекта можно присвоить (или скопировать указатель на асинхронно-изменяемый тип) только асинхронно-изменяемому указателю. При инициализации ссылки на асинхронно-изменяемый объект следует использовать только асинхронно-изменяемые ссылки.

Синтезируемые функции управления копированием не применимы к асинхронно-изменяемым объектам

Между константными и асинхронно-изменяемыми объектами есть одно важное различие: для инициализации и присвоения асинхронно-изменяемых объектов не применимы синтезируемые версии операторов присвоения, копирования и перемещения. Синтезируемые функции-члены управления копированием получают параметры, типами которых являются константные ссылки на класс. Однако асинхронно-изменяемый объект не может быть передан при помощи обычной или константной ссылки.

Если класс должен обеспечить копирование, перемещение или присвоение асинхронно-изменяемых объектов в (или из) асинхронно-изменяемый операнд, в нем следует определить его собственные версии операторов копирования и перемещения. Например, объявив параметры как ссылки const и volatile, можно обеспечить копирование или присвоение из любого вида типа Foo:

class Foo {

public:

 Foo(const volatile Foo&); // копирование из объекта volatile

 // присвоение объекта volatile обычному объекту

 Foo& operator=(volatile const Foo&);

 // присвоение объекта volatile объекту volatile

 Foo& operator=(volatile const Foo&) volatile;

 // остальная часть класса Foo

};

Хотя для объектов volatile вполне можно определить функции копирования и присвоения, возникает вполне резонный вопрос: имеет ли смысл копировать объект volatile? Ответ зависит от причины использования такого объекта в конкретной программе.

19.8.3. Директивы компоновки: extern "C"

Иногда в программах С++ необходимо применять функции, написанные на другом языке программирования. Как правило, это язык С. Подобно любому имени, имя функции, написанной на другом языке, следует объявить. Это объявление должно указать тип возвращаемого значения и список параметров. Компилятор проверяет обращения к внешним функциям на другом языке точно так же, как и обращения к обычным функциям языка С++. Однако для вызова функций, написанных на других языках, компилятор обычно вынужден создавать иной код. Чтобы указать язык для функций, написанных на языке, отличном от С++, используются директивы компоновки (linkage directive).

Комбинация кода С++ с кодом, написанным на любом другом языке, включая язык С, требует доступа к компилятору этого языка, совместимому с вашим компилятором С++.

Объявление функций, написанных на языке, отличном от С++

Директива компоновки может существовать в двух формах: одиночной и составной. Директивы компоновки не могут располагаться в определении класса или функции. Некоторые директивы компоновки должны присутствовать в каждом объявлении функции.

В качестве примера рассмотрим некоторые из функций языка С, объявленные в заголовке cstdlib:

// гипотетические директивы компоновки, которые могли бы

// присутствовать в заголовке С++ <cstring>

// одиночная директива компоновки

extern "С" size_t strlen(const char *);

// составная директива компоновки

extern "С" {

 int strcmp(const char*, const char*);

 char *strcat(char*, const char*);

}

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

Строковый литерал указывает язык, на котором написана функция. Используемый компилятор обязан поддерживать директивы компоновки для языка С. Компилятор может поддерживать директивы компоновки и для других языков, например extern "Ada", extern "FORTRAN" и т.д.

Директивы компоновки и заголовки

Та же директива компоновки может быть применена к нескольким функциям одновременно. Для этого их объявления заключают в фигурные скобки после директивы компоновки. Эти фигурные скобки служат для группировки объявлений, к которым применяется директива компоновки. Эти фигурные скобки игнорируются, а имена функций, объявленных в их пределах, видимы, как будто функции были объявлены вне фигурных скобок.

Составная форма объявления применима ко всему файлу заголовка. Например, заголовок cstring языка С++ может выглядеть следующим образом.

// составная директива компоновки

extern "С" {

#include <string.h> // функции языка С, манипулирующие строками

                    // в стиле С

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*