Программирование >>  Инициализация объектов класса, структура 

1 ... 208 209 210 [ 211 ] 212 213 214 ... 395


typedef unsigned int Bit;

class File { public:

Bit mode: 2; Bit modified: 1;

Bit prot owner: 3; Bit prot group: 3;

Bit prot world: 3; ...

unsigned int, ассоциированном с первым полем mode:

Доступ к битовому полю осуществляется так же, как к прочим членам класса. Скажем, к битовому полю, являющемуся закрытым членом класса, можно обратиться лишь из

oid File::write()

modified = 1;

...

void File::close()

if ( modified )

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

функций-членов и друзей этого класса:

Вот простой пример использования битового поля длиной больше 1 (примененные здесь

enum { READ = 01, WRITE = 02 }; режиме! открытия файла

int main() { File myFile;

myFile.mode = READ;

if ( myFile.mode s READ )

cout << myFile.mode is set to REA\D\n ;

побитовые операции рассматривались в разделе 4.11):

Обычно для проверки значения битового поля-члена определяются встроенные функции-члены. Допустим, в классе File можно ввести члены isRead() и isWrite() :

После идентификатора битового поля следует двоеточие, а за ним - константное выражение, задающее число битов. К примеру, modified - это поле из одного бита.

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



inline int File::isRead() { return mode S READ; } inline int File::isWrite() { return mode S WRITE; }

if ( myFile.isRead() ) /* ... */

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

К битовому нолю нельзя применять оператор взятия адреса (S), поэтому не может быть и указателя на подобные поля-члены. Кроме того, полю запрещено быть статическим членом.

В стандартной библиотеке C++ имеется шаблон класса bitset, который облегчает манипуляции с битовыми множествами. Мы рекомендуем использовать его вместо битовых нолей. (Шаблон класса bitset и определенные в нем операции рассматривались в разделе 4.12.)

Упражнение 13.17

Перепишите примеры из этого подраздела так, чтобы в классе File вместо объявления и прямого манипулирования битовыми полями использовался класс bitset и его операторы.

13.9. Область видимости класса A

Тело класса определяет область видимости. Объявления членов класса внутри тела вводят их имена в область видимости класса.

Для обращения к ним применяются операторы доступа (точка и стрелка) и оператор разрешения области видимости (::). Когда употребляется оператор доступа, то предшествующее ему имя обозначает объект или указатель на объект типа класса, а следующее за ним имя должно находиться в области видимости этого класса. Аналогично при использовании оператора разрешения области видимости поиск имени, следующего за ним, идет в области видимости класса, имя которого стоит перед оператором. (В главах 17 и 18 мы увидим, что производный класс может обращаться к членам своих базовых.)

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

class String {

public:

typedef int index type;

тип параметра - это на самом деле String::index type charS operator[]( index type )

объявления:

Порядок объявления членов класса в его теле важен: нельзя ссылаться на члены, которые будут объявлены позже. Например, если объявление оператора operator[]() находится



class String { public:

ошибка: имя index type не объявлено char soperator[]( index type );

typedef int index type;

имя index type: };

Однако из этого правила есть два исключения. Первое касается имен, использованных в определениях встроенных функций-членов, второе - имен, применяемых как аргументы по умолчанию. Рассмотрим обе ситуации.

Разрешение имен в определениях встроенных функций-членов происходит в два этапа. Сначала объявление функции (т.е. тип возвращаемого значения и список параметров) обрабатывается в том месте, где оно встретилось в определении класса. Затем тело функции обрабатывается во всей области видимости, сразу после того, как были просмотрены объявления всех членов. Посмотрим на наш пример, в котором оператор

class String {

public:

typedef int index type; char soperator[]( index type elem ) { return string[ elem ]; } private:

char * string;

operator[]() определен как встроенный внутри тела класса: };

На первом этапе просматриваются имена, использованные в объявлении operator[]() , чтобы найти имя типа параметра index type. Поскольку первый шаг выполняется тогда, когда в теле класса встретилось определение функции-члена, то имя index type должно быть объявлено до определения operator[]() .

Обратите внимание, что член string объявлен в теле класса после определения operator[] (). Это правильно, и string не является в теле operator[]() необъявленным именем. Имена в телах функций-членов просматриваются на втором шаге разрешения имен в определениях встроенных функций-членов. Этот этап выполняется во всей области видимости класса, как если бы тела функций-членов обрабатывались последними, прямо перед закрытием тела класса, когда все его члены уже объявлены.

Аргументы по умолчанию также разрешаются на втором шаге. Например, в объявлении функции-члена clear() используется имя статического члена bkground, который определен позже:

раньше объявления typedef index type, то приведенное ниже объявление operator[]() оказывается ошибочным, поскольку в нем используется еще неизвестное



1 ... 208 209 210 [ 211 ] 212 213 214 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика