Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / C / C++ / Введение в язык C++ / Классы /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Друзья и Объединения - Программирование от RIN.RU
Друзья и Объединения



Структуры и Объединения


По определению struct - это просто класс, все члены которого общие, то есть


struct s { ...


есть просто сокращенная запись


class s { public: ...


Структуры используются в тех случаях, когда скрытие данных неуместно.


Именованное объединение определяется как struct, в которой все члены имеют один и тот же адрес. Если известно, что в каждый момент времени нужно только одно значение из структуры, то объединение может сэкономить пространство. Например, можно определить объединение для хранения лексических символов C компилятора:


union tok_val {
char* p; // строка
char v[8]; // идентификатор (максимум 8 char)
long i; // целые значения
double d; // значения с плавающей точкой
};


Сложность состоит в том, что компилятор, вообще говоря, не знает, какой член используется в каждый данный момент, поэтому надлежащая проверка типа невозможна.


Например:


void strange(int i)
{
tok_val x;
if (i)
x.p = "2";
else
x.d = 2;
sqrt(x.d); // ошибка если i != 0
}


Кроме того, объединение, определенное так, как это, нельзя инициализировать.


Например:


tok_val curr_val = 12; // ошибка: int присваивается tok_val"у


является недопустимым. Для того, чтобы это преодолеть, можно воспользоваться конструкторами:


union tok_val {
char* p; // строка
char v[8]; // идентификатор (максимум 8 char)
long i; // целые значения
double d; // значения с плавающей точкой




tok_val(char*); // должна выбрать между p и v
tok_val(int ii) { i = ii; }
tok_val() { d = dd; }
};


Это позволяет справляться с теми ситуациями, когда типы членов могут быть разрешены по правилам для перегрузки имени функции (см. этот раздел и этот пункт).


Например:


void f()
{
tok_val a = 10; // a.i = 10
tok_val b = 10.0; // b.d = 10.0
}


Когда это невозможно (для таких типов, как char* и char[8], int и char, и т.п.), нужный член может быть найден только посредством анализа инициализатора в ходе выполнения или с помощью задания дополнительного параметра.


Например:


tok_val::tok_val(char* pp)
{
if (strlen(pp) <= 8)
strncpy(v,pp,8); // короткая строка
else
p = pp; // длинная строка
}


Таких ситуаций вообще-то лучше избегать.


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


class tok_val {
char tag;
union {
char* p;
char v[8];
long i;
double d;
};
int check(char t, char* s)
{ if (tag!=t) { error(s); return 0; } return 1; }
public:
tok_val(char* pp);
tok_val(long ii) { i=ii; tag="I"; }
tok_val(double dd) { d=dd; tag="D"; }




long& ival() { check("I","ival"); return i; }
double& fval() { check("D","fval"); return d; }
char*& sval() { check("S","sval"); return p; }
char* id() { check("N","id"); return v; }
};


Конструктор, получающий строковый параметр, использует для копирования коротких строк strncpy(). strncpy() похожа на strcpy(), но получает третий параметр, который указывает, сколько символов должно копироваться:


tok_val::tok_val(char* pp)
{
if (strlen(pp) <= 8) { // короткая строка
tag = "N"
strncpy(v,pp,8); // скопировать 8 символов
}
else { // длинная строка
tag = "S"
p = pp; // просто сохранить указатель
}
}


Тип tok_val можно использовать так:


void f()
{
tok_val t1("short"); // короткая, присвоить v
tok_val t2("long string"); // длинная строка, присвоить p
char s[8];
strncpy(s,t1.id(),8); // ok
strncpy(s,t2.id(),8); // проверка check() не пройдет
}


<<<  Назад
 1  2  3  4 


 8  Комментарии к статье  8 8  Обсудить в чате

8  В тему

Знакомство и краткий обзор

Классы и Члены

Интерфейсы и Реализации

Конструкторы и Деструкторы

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь