|
Программирование >> Инициализация объектов класса, структура
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; битовое поле знака:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |