Страница 2 из 2

Добавлено: 13 июл 2005, 15:17
BreakPointMAN
Я сделал это так (продолжая изобретение велосипеда и занимаясь извратом :D ):
- вынес все в отдельный класс
- добавил параметризацию, сделав класс шаблонным
- добавил специализацию для типа char*
- ввел в интерфейс класса функтор - указатель на функцию проверки условия, должно присваиваться или нет... в принципе, если условиям r-value не подходит, можно выбрасывать исключение - так вроде правильнее будет...

Вот код:

Код: Выделить всё

#ifndef __PROPERTY_H
#define PROPERTY_H
template <class T>
class PROPERTY
   {
    private:
       T data;
    public:
       PROPERTY();
       PROPERTY(T _data);
       operator T() const;
       PROPERTY (const PROPERTY&);
       PROPERTY& operator=(const PROPERTY& rhs);
       ~PROPERTY();
       bool(*Condition)(T);

   };
#endif
#ifndef __PROPERTY_CPP
#define PROPERTY_CPP


// шаблон - конструктор по умолчанию
template <class T>
   PROPERTY<T>::PROPERTY():Condition(NULL){/*data(NULL)*/};

// шаблон - конструктор, принимающий параметр типа T
template <class T>
   PROPERTY<T>::PROPERTY(T _data):Condition(NULL){data=_data;}

// шаблон - операция преобразования
template <class T>
   PROPERTY<T>::operator T() const
      {return data;}

// шаблон - операция присваивания
template <class T>
   PROPERTY<T>& PROPERTY<T>::operator=(const PROPERTY<T>& rhs)
      {
       if(this==&rhs) return *this;
       if(Condition==NULL)
          {
           data=rhs.data;
          }
       else
          {
           if(Condition(rhs.data)) data=rhs.data;
          }
       return *this;
      }

// шаблон - конструктор копирования
template <class T>
   PROPERTY<T>::PROPERTY(const PROPERTY<T>&):Condition(NULL){};

// шаблон - деструктор
template <class T>
   PROPERTY<T>::~PROPERTY(){}

// **********       Специализация для char *        **********



// char*  - конструктор по умочанию
PROPERTY<char*>::PROPERTY():Condition(NULL)
   {
    data=new char[1]; data[0]='\0';
   }

// char* - конструктор, принимающий строку
PROPERTY<char*>::PROPERTY(char* _data):Condition(NULL)
   {
    int tmp=strlen(_data);
    data=new char[tmp+1];
    strcpy(data, _data);
    data[tmp]='\0';
   }

// char* - операция присваивания
   PROPERTY<char*>& PROPERTY<char*>::operator=(const PROPERTY<char*>& rhs)
      {
       if(this==&rhs) return *this;
       if(Condition==NULL)
          {
           delete data;
           int tmp=strlen(rhs.data);
           data=new char[tmp+1];
           strcpy(data,rhs.data);
           data[tmp]='\0';
           }
       else
          {
           if(Condition(rhs.data))
              {
               delete data;
               int tmp=strlen(rhs.data);
               data=new char[tmp+1];
               strcpy(data,rhs.data);
               data[tmp]='\0';
             }
          }
       return *this;
      }


// char* - деструктор
PROPERTY<char*>:: ~PROPERTY()
   {
    delete data;
   }

// char* - конструктор копирования
PROPERTY<char*>::PROPERTY(const PROPERTY<char*>& rhs):Condition(NULL)
   {
    data=NULL;
    operator=(rhs);
   }
#endif

Юзается примерно так:

Код: Выделить всё


// Определяем св-во x - работает как целочисленная переменная
PROPERTY<int> x;

//    Определяем функцию, накладывающую условие на присваиваемое значение,
// в данном  случае оно должно быть в диапазоне [-10;10]
bool f(int arg)
   {
       if(arg<-10 || arg >10)
          {
           cout <<"\nRange error!\n";
           return false;
          }
       else
          return true;
   } 

// Устанавливаем это условие на наше св-во x
x.Condition=f; 

x=5; // присвоится
x=-5; // присвоится
x=14; // не присвоится

Как потом выяснилось, в BCB и MSVC уже есть property, реализованы они, конечно, по-разному, и менее извращенно, но суть примерно такая. Так что можно было не изобретать велосипед... %)

Добавлено: 19 июл 2005, 13:51
WinMain
В шаблонах свойств лучше не специализировать тип char*, пусть он останется как есть, а для хранения строк лучше использовать специальные классы типа CString или std::string. Но это вся эта стилизация кода под другой язык программирования останется лишь декорацией и не будет иметь реального смысла, если она не связана с конкретной методикой решения той или иной задачи. Ведь в чём смысл использования высокоуровневых сред разработки и языков программирования высокого уровня - это реализация некой методики и предоставление соответствующих инструментов для решения определённого круга задач. Ведь если взять тот же Delphi или Visual Basic, то в них программное изменение свойства компонента сопровождается изменением его визуального представления или обновлением записи в базе данных, либо какими-то другими действиями. А если в твоих шаблонах свойств изменения данных не сопровождаются никакими действиями по представлению данных или обмену данными, то вся эта овчинка выделки не стоит.