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

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


union TokenValue { public:

TokenValue(int ix) : ival(ix) { } TokenValue(char ch) : cval(ch) { } ...

int ival() { return ival; } char cval() { return cval; } private:

int ival; char cval;

...

int main() {

TokenValue tp(10);

int ix = tp.ival();

enum TokenKind ( ID, Constant /* и другие тип1 лексем */ }

class Token { public:

TokenKind tok; TokenValue val;

Вот пример работы объединения TokenValue:

int lex() {

Token curToken; char *curString; int curIval;

case ID: идентификатор curToken.tok = ID; curToken.val. sval = curString;

break;

case Constant: целая константа curToken.tok = Constant; curToken.val. ival = curIval;

break;

... и т. д.

Объект типа Token можно использовать так:

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



class Token { public:

TokenKind tok;

имя типа объединения опущено union {

char cval; int ival;

char * sval; double dval;

-а 1 .

} val;

выше, но без указания имени:

Существует анонимное объединение - объединение без имени, за которым не следует определение объекта. Вот, например, определение класса Token, содержащее анонимное объединение:

Чтобы защититься от подобного рода ошибок, следует создать дополнительный объект, дискриминант объединения, определяющий тип значения, которое в данный момент

char *idVal;

проверить значение дискриминанта перед тем, как обращаться к sval if ( curToken.tok == ID )

хранится в объединении. В классе Token роль такого объекта играет член tok:

idVal = curToken.val. sval; При работе с объединением, являющимся членом класса, полезно иметь набор функций

#include <cassert>

функции доступа к члену объединения sval

string Token::sval() { assert( tok==ID );

return val. sval; для каждого хранящегося в объединении типа данных:

Имя в определении объединения задавать необязательно. Если оно не используется в программе как имя типа для объявления других объектов, его можно опустить. Например, следующее определение объединения Token эквивалентно приведенному



class Token { public:

TokenKind tok;

анонимное объединение

char cval; int ival; char * sval; double dval;

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

int lex() {

Token curToken; char *curString; int curIval;

... выяснить, что находится в лексеме ... затем установить curToken

case

curToken.tok = ID; curToken. sval = curString;

break;

case Constant: целая константа curToken.tok = Constant; curToken. ival = curIval; break;

... и т. д.

предыдущее определение:

Анонимное объединение позволяет убрать один уровень доступа, поскольку обращение к его членам идет как к членам класса Token. У него не может быть закрытых или защищенных членов, а также функций-членов. Такое объединение, определенное в глобальной области видимости, должно быть объявлено в безымянном пространстве имен или иметь модификатор static.

13.8. Битовое поле - член, экономящий память

Для хранения заданного числа битов можно объявить член класса специального вида, называем1й битовым полем. Он должен иметь цел1й тин данных, со знаком или без

class File { ...

unsigned int modified : 1; битовое поле знака:



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

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