Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] Непонятка при присвоении значения переменной, имеющей тип: перечисление. (http://forum.oszone.net/showthread.php?t=124665)

Oleg_SK 01-12-2008 11:08 968820

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

enum COLOR {test_1, test_2, test_3, test_4, test_5};
, который создает новый тип-перечисление COLOR и задает для него пять возможных значений. Теперь по идее, если создать переменную с типом COLOR, ей можно будет присвоить только одно из этих пяти значений, а попытка присвоить какое-либо отличное значение должно привести к ошибке. Верно я понимаю? Идем дальше: каждой константе перечисления соответствует определенное целочисленное значение. Например:
test_1 - 0
test_2 - 1
test_3 - 2
test_4 - 3
test_5 - 4
Таким образом, по идее, если я создам переменную с типом COLOR:
Код:

COLOR vartest;
, то в последствии смогу присвоить ей лишь те значения, которые указывались при описании перечисления. Например так:
Код:

vartest = test_5;
, или так:
Код:

vartest = (COLOR) 4;
Никаких проблем при этом, как и следовало ожидать, не возникает. Непонятка возникает в том случае, если присвоить переменной vartest значение, которое не было указано при описании перечисления COLOR. Дело в том, что компилятор не считает такой код ошибочным (при компиляции нет ни ошибок, ни предупреждений), и действительно в процессе работы программы переменной vartest присваивается левое значение... Например:
Код:

vartest = (COLOR) 1000;
Мне хотелось бы знать: это я не правильно понимаю суть работы с перечислениями, или компилятор (Visual C++ 6.0)? Почему компилятор не пресекает подобные действия?

pva 01-12-2008 11:58 968852

Цитата:

Цитата Oleg_SK
vartest = (COLOR) 4; »

это грубый хак. Когда используются сишные, а не плюсплюсные преобразования типов, используются сишные правила. А они это позволяют. Чтобы такого не было, нужно в настройках компилятора поставить галочку, запрещающую преобразование int в enum

Oleg_SK 03-12-2008 13:21 971058

pva
Цитата:

Цитата pva
Когда используются сишные, а не плюсплюсные преобразования типов, используются сишные правила. А они это позволяют. »

Понятно... Подскажите, плиз, как сделать сиплюсплюсное приведение типа, чтобы указанная выше ситуация пресекалась? В том месте книги, где я читаю указано только два варианта для этого действия:
1) Я им пользовался в своем примере в первом посте;
2) С помощью static_cast. Например:
Код:

vartest = static_cast <COLOR> (1000);
В обоих случаях имеет место обсуждаемая непонятка.
Цитата:

Цитата pva
Чтобы такого не было, нужно в настройках компилятора поставить галочку, запрещающую преобразование int в enum »

Мне хотелось бы сохранить возможность преобразования int в enum.

P.S: Неужели придется писать свой код, контролирующий корректность значения int перед его преобразованием в enum? Хотелось бы этого избежать...
P.S.S: По ходу изучения работы с перечислениями я столкнулся с еще одной непоняткой. Проблема в том, что компилятор не дает мне при создании нескольких разных типов-перечислений использовать в качестве одного из их возможных значений одноименную константу. Сразу скажу, что технически я понимаю почему это происходит. Мне не понятно: почему так сделали? Зачем сделали возможные значения перечислений доступными коду как обычные константы?

pva 03-12-2008 15:16 971160

Цитата:

Цитата Oleg_SK
Мне хотелось бы сохранить возможность преобразования int в enum. »

зачем? так хочешь чтобы преобразовывалось(противоречит первому посту) или нет?
Цитата:

Цитата Oleg_SK
Проблема в том, что компилятор не дает мне при создании нескольких разных типов-перечислений использовать в качестве одного из их возможных значений одноименную константу »

это чтобы не перепутать:
Код:

enum ColumnAlign
{
  left, right, center
};

enum RectField
{
  left, right, bottom, top
};

void Column::setAlign(ColumnAlign);
void MyRect::getField(RectField);
void MyLink::attach(ColumnAlign, RectField);

Цитата:

Цитата Oleg_SK
Зачем сделали возможные значения перечислений доступными коду как обычные константы? »

А что это ещё? помойму они и есть

Oleg_SK 03-12-2008 19:27 971435

pva
Цитата:

Цитата pva
это чтобы не перепутать: »

Цитата:

Цитата pva
А что это ещё? помойму они и есть »

Понятно... Придется приспосабливаться, но все равно остается чувство, что это не правильно (во всяком случае, я бы это сделал не так). Ну да ладно - не впервой...

pva 04-12-2008 07:22 971866

Меня в enum смущает только одно:
Код:

class ListView
{
public:
    enum column_align_t {ca_left, ca_right, ca_center};
    ...
};

// правильно так:
listView1.setColumnAlign(1, ListView::ca_left);
// но логичней так:
// listView1.setColumnAlign(1, ListView::column_align_t::ca_left);

тем не менее, как видно из примера, указание имени перечисления усложняет чтение и почти не вносит большей понятности в код. Хотя когда этих enum с десяток, нужно грамотно называть их элементы, чтоб не запутаться. Я как правило называю элементы enum XXX_t именами XXX_value
не забываем помечать решённую тему ;-)


Время: 02:28.

Время: 02:28.
© OSzone.net 2001-