Последние изменения - Поиск:
RSS блога RSS блога

Начало

Блог

Программки

    Google+

Плагины

Программирование

Фото

Контакты

Я в твиттере Я в ЖЖ

safe_val

safe_val - Класс следит за тем, чтобы не использовались значения неинициализированных переменных

Зачем этот класс нужен

Представьте ситуацию, что у вас есть какая-то структура, которая заполняется постепенно, например, парсится текстовый файл и из него заполняются соответствующие поля. А потом по этой структуре происходит какое-то действие в зависимости от значения этих самых полей структуры. Чтобы быть более точным, приведу пример "из жизни", который и заставил меня заняться этим классом. Задача состояла в том, что я читал из текстового файла, строки которого представляют собой выражения вида имя_параметра = значение, имена параметров и их значения, которые сохранялись в структуру. Позже по этой структуре создается элемент GUI. Так вот важно, чтобы все поля структуры были бы инициализированы, то есть не был бы пропущен ни один параметр. А структуры заполняются разные и количество параметров у них разное.

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

Что делает класс

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

Что где скачать

Здесь лежит сам класс (см. файл save_val\safe_val.h), документация, сгенерированная программой Doxygen (doc\safe_val.chm) и тестовые примеры, которые написаны под класс CTinyTest (это такой доморощенные маааленький UnitTest, описание которого я выкладывал здесь). Пример работает под Visual C++ 7.0. Сам класс (safe_val) работает и под 6-й студией.

Шаблонные параметры класса

Класс объявлен следующим образом:

template <typename TVal, typename TDefManager = throw_def<TVal> >
 class safe_val
 {
        ...
 }

TVal - это тип хранимого значения.
А вот TDefManager определяет поведение класса при попытке получения значения еще неинициализированного значения. Для этого TDefManager должен иметь статический public метод, который может быть объявлен следующим образом:

static TVal defvalue()

То есть иметь имя defvalue и возвращать значение, тип которого соответствует хранимому типу в классе.

В файле safe_val.h уже определены 2 таких типа. Это throw_def, который бросает исключение uninit_val и def_val, который возвращает значение по умолчанию для данного типа, т.е. TVal().

Как использовать класс

Во-первых, надо подключить заголовочный файл save_val.h через директиву #include. А, во-вторых, объявить переменную типа safe_val. У него несколько конструкторов, поэтому объявлять можно по-разному:

// Создание неинициализированной переменной
 safe_val<int> ival1;

 // Создание инициализированной переменной
 safe_val<int> ival2(5);
 safe_val<int> ival3 = 6;
 safe_val<int> ival4 (ival1);

А дальше вы используете класс как обычную переменную. Например,

int a = ival2;
 ival1 = 10;

Можно получить значение напрямую, вызвав метод value().

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

safe_val и структуры

В принципе, этот класс создавался для хранения простых типов внутри структуры, т.е. так, чтобы подобная структура:

struct SafeStruct
 {
        safe_val<int> ival;
        safe_val<float> fval;
 }

Гарантированно была бы инициализирована. Поэтому, если забыть инициализировать, например, ival, то при попытке получить это значение или даже просто скопировать структуру в другую переменную, происходит исключение (или др. поведение).

Но, в принципе, никто не запрещает хранить в safe_val и сами структуры или классы при условии, что они будут инициализироваться сразу и при этом надо быть готовым к тому, что иногда придется получать значение через value(). Это "иногда" будет тогда, когда вам нужно будет обратиться к члену структуры. В том контексте, в котором я использовал класс, там хранились переменные типа std::string.



Подписаться на комментарии
Автор:
Тема:
 Ваш комментарий
 
 
Введите код 272
 
Править - История - Печать - Последние изменения - Поиск
Последняя редакция от 13.12.2008 10:19