Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Можно ли реализовать свойства шаблонного класса?

5.3K
13 октября 2008 года
!Волк
95 / / 19.07.2006
Вот пример обычного описания свойства для записи и использование его в тестовом классе sample_t.

Код:
// Описание свойства только для записи
template<class owner_t, class value_t>
struct domen_write_only_t
{
  typedef void (owner_t::*set_method_t) (const value_t &);
 
  template<set_method_t set_method>
  class property_write_only_t
  {
    owner_t& m_owner;
    public:
    property_write_only_t(owner_t& a_owner) : m_owner(a_owner) { ; }
    const value_t& operator = (const value_t& a_value)
    {
      (m_owner.*set_method)(a_value);
      return a_value;
    }
  };
};
 
 
class sample_t
{
  private:
  double m_val;
  public:
 
  void set_value(const double& a_val)
  {
    m_val = a_val;
  }
  domen_write_only_t<sample_t, double> ::
  property_write_only_t <set_value> val;
  sample_t(): m_val(0.), val(*this)
  {
  }
};

Здесь для простоты приведен пример свойства, реализующего только запись.

Возможно ли реализовать подобные свойства для шаблонного класса?
Например для класса sample2_t:

Код:
template<class T>
class sample2_t
{
private:
  T m_val;
public:
  void set_value(const T& a_val)
  {
    m_val = a_val;
  }
  sample2_t(): m_val(0)
  {
  }
};
Страницы:
3
13 октября 2008 года
Green
4.8K / / 20.01.2000
Ну для начала скажу, что такого рода конструкции хороши лишь для академических упражнений. Код реальных программ они лишь усложняют. Я бы обрывал руки за такие ухищрения. Проще и понятнее делать так:
Код:
template<class T>
class sample2_t
{
private:
  T m_val;

public:
  void set_value(const T& a_val) {
    m_val = a_val;
  }

  sample2_t(): m_val() {
  }
};

Безо всяких "свойств" (на самом деле это прокси поля класса)!
Метода set_value вполне достаточно.

Но для любителей извращений вот код с шаблонами:
Код:
template<class owner_t, class value_t>
class property_write_only_t
{
private:
    typedef void(owner_t::*set_method_t)(const value_t&);

    owner_t& m_owner;
    set_method_t m_set_method;

public:
    property_write_only_t(owner_t& a_owner, set_method_t m_set_method)
        : m_owner(a_owner), m_set_method() {}

    const value_t& operator = (const value_t& a_value) {
        (m_owner.*m_set_method)(a_value);
        return a_value;
    }
};


template<class T>
class sample_t
{
private:
    T m_val;

public:
    void set_value(const T& a_val) {
        m_val = a_val;
    }

    property_write_only_t<sample_t, T> val;

    sample_t()
        : m_val(), val(*this, &sample_t::set_value) {}
};
5.3K
14 октября 2008 года
!Волк
95 / / 19.07.2006
Почему усложняет?
Строчка
 
Код:
sample.val = 1;

выглядит гораздо красивее, чем
 
Код:
sample.set_value(1);

Она будет понятна даже человеку, не знающему английский:)

По поводу приведенного тобой решения.
К сожалению оно у меня не захотело работать. На Microsoft Visual 2005 скомпилилось, но при обращении к свойству происходит обращение по нулевому адресу.
На Buider 6 вообще не захотело компилироваться.
Я заменил строку
 
Код:
property_write_only_t<sample_t, T> val;

на
 
Код:
property_write_only_t<sample_t<T>, T> val;

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

Может при работе с указателями на шаблонные методы существует какая то специфика? Хотелось бы также, чтобы указатель на шаблонный метод полностью передавался в качестве параметра шаблона, а не как параметр конструктора. Если конечно это возможно.
11
14 октября 2008 года
oxotnik333
2.9K / / 03.08.2007
http://rsdn.ru/?article/vcpp/props.xml
5.3K
14 октября 2008 года
!Волк
95 / / 19.07.2006



Ну то что там реализовано у меня не получилось правильно запустить с шаблонным классом. Проблема таже, при обращении к свойству происходит обращение по нулевому адресу. Или может я что то не так делаю? Если у тебя работает, не мог бы ты привести пример, как правельно передать указатели на шаблонные методы.

11
14 октября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: !Волк
Ну то что там реализовано у меня не получилось правильно запустить с шаблонным классом. Проблема таже, при обращении к свойству происходит обращение по нулевому адресу. Или может я что то не так делаю? Если у тебя работает, не мог бы ты привести пример, как правельно передать указатели на шаблонные методы.


пример из ссылки под VS2005 работает, правда немножко пришло подкорректировать (выделил места):

Код:
template <typename proptype, typename propowner> class property_
{
protected:
    typedef proptype (propowner::*getter)();
    typedef void (propowner::*setter)(proptype);
    propowner * m_owner;
    getter m_getter;
    setter m_setter;
public:
    // Оператор приведения типа. Реализует свойство для чтения.
    operator proptype()
    {
        // Здесь может быть проверка "m_owner" и "m_getter" на NULL
        return (m_owner->*m_getter)();
    }
    // Оператор присваивания. Реализует свойство для записи.
    void operator =(proptype data)
    {
        // Здесь может быть проверка "m_owner" и "m_setter" на NULL
        (m_owner->*m_setter)(data);
    }
    // Конструктор по умолчанию.
    property_() :
        m_owner(NULL),
        m_getter(NULL),
        m_setter(NULL)
    {
    }
    //Конструктор инициализации.
    property_(propowner * const owner, getter getmethod, setter setmethod) :
        m_owner(owner),
        m_getter(getmethod),
        m_setter(setmethod)
    {
    }
    // Инициализация
    void init(propowner * const owner, getter getmethod, setter setmethod)
    {
        m_owner = owner;
        m_getter = getmethod;
        m_setter = setmethod;
    }
};

class CValue
{
private:
    int m_value;
    int get_Value()
    {
        return m_value;    // Или более сложная логика
    }
    void put_Value(int value)
    {
        m_value = value;     // Или более сложная логика
    }
public:
    property_ <int, CValue> Value;
    CValue()
    {
        Value.init(this, &CValue::get_Value, &CValue::put_Value);
    }
};
5.3K
14 октября 2008 года
!Волк
95 / / 19.07.2006
oxotnik333, ты не понял). Ксласс CValue должен быть шаблонным:
Код:
template<class T>
class CValue
{
private:
    T m_value;
    T get_Value()
    {
        return m_value;    // Или более сложная логика
    }
    void put_Value(T value)
    {
        m_value = value;     // Или более сложная логика
    }
public:    
    CValue()
    {
    }
};


Как для такого класса свойства реализовать?
3
14 октября 2008 года
Green
4.8K / / 20.01.2000
Цитата: !Волк

Почему усложняет?
Строчка
 
Код:
sample.val = 1;

выглядит гораздо красивее, чем
 
Код:
sample.set_value(1);

Она будет понятна даже человеку, не знающему английский:)


Я не вижу в этом красоты.
Усложняет потому, что делает код менее читабельным и интуитивно понятным.
Видя запись sample.val = 1; я предполагаю, что val является открытым (public) полем класса, у поля естественно есть определенный тип, что этому полю присваивается значение, ну или вызывается operator= для данного типа.
Но на самом деле поля такого нет, значение записывается в совершенно иное поле неизвестного типа и ещё не известно какое значение.
Для того, чтобы понять доступно ли такое "свойство" по чтению или по записи надо либо перелопатить исходники (лишь в академическом примере это просто), либо обломаться при компиляции. А скорее, сначала обломаться при компиляции, а потом долго думать и лопатить исходники на предмет "а в чем собственно проблема".
Ещё можно подумать на счет "веселостей", которые возможно появятся при наследовании.

Цитата: !Волк

По поводу приведенного тобой решения.
К сожалению оно у меня не захотело работать. На Microsoft Visual 2005 скомпилилось, но при обращении к свойству происходит обращение по нулевому адресу.


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

 
Код:
property_write_only_t(owner_t& a_owner, set_method_t set_method)
        : m_owner(a_owner), m_set_method(set_method) {}


Цитата: !Волк

На Buider 6 вообще не захотело компилироваться.


Ну, горе-компиляторы мы рассматривать не будем.

Цитата: !Волк

Хотелось бы также, чтобы указатель на шаблонный метод полностью передавался в качестве параметра шаблона, а не как параметр конструктора. Если конечно это возможно.


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

Код:
template<class owner_t, class value_t, void(owner_t::*set_method_t)(const value_t&)>
class property_write_only_t
{
private:
    owner_t& m_owner;

public:
    property_write_only_t(owner_t& a_owner)
        : m_owner(a_owner) {}

    const value_t& operator = (const value_t& a_value) {
        (m_owner.*set_method_t)(a_value);
        return a_value;
    }
};

template<class T>
class sample_t
{
private:
    T m_val;

public:
    void set_value(const T& a_val);

    property_write_only_t<sample_t, T, &sample_t::set_value> val;

    sample_t()
        : m_val(), val(*this) {}
};

template<class T>
void sample_t<T>::set_value(const T& a_val) {
    m_val = a_val;
}

Только чем не нравится параметр конструктора?
Да и вообще, зачем этот огород?
Понятнее и проще (в написании, отладке и т.п.) все тот же set_value !
11
15 октября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: !Волк
oxotnik333, ты не понял). Ксласс CValue должен быть шаблонным:
Как для такого класса свойства реализовать?



а что это меняет? и так

 
Код:
template <class T>
class CValue

работает
246
15 октября 2008 года
GIZMO
1.8K / / 30.07.2004
Цитата: Green
Я не вижу в этом красоты.
Усложняет потому, что делает код менее читабельным и интуитивно понятным.
Видя запись sample.val = 1; я предполагаю, что val является открытым (public) полем класса, у поля естественно есть определенный тип, что этому полю присваивается значение, ну или вызывается operator= для данного типа.
Но на самом деле поля такого нет, значение записывается в совершенно иное поле неизвестного типа и ещё не известно какое значение.
Для того, чтобы понять доступно ли такое "свойство" по чтению или по записи надо либо перелопатить исходники (лишь в академическом примере это просто), либо обломаться при компиляции. А скорее, сначала обломаться при компиляции, а потом долго думать и лопатить исходники на предмет "а в чем собственно проблема".
Ещё можно подумать на счет "веселостей", которые возможно появятся при наследовании.


херня полная...

3
15 октября 2008 года
Green
4.8K / / 20.01.2000
Цитата: GIZMO
херня полная...


Что именно?
С чем конкретно ты не согласен?
Ты считаешь, что использование таких вот "свойств" чем-то удобно? Обоснуй.

5
15 октября 2008 года
hardcase
4.5K / / 09.08.2005
Нда. Кошмар.

Свойства - клевая штука, но это заявление не имеет отношения к C++.
Уж лучше геттеры-сеттеры, чем черте какой ужас через шаблоны, раз нету аналога борландовских пропертей.
4.3K
15 октября 2008 года
flat
142 / / 27.12.2005
Цитата: hardcase
Нда. Кошмар.

Свойства - клевая штука, но это заявление не имеет отношения к C++.
Уж лучше геттеры-сеттеры, чем черте какой ужас через шаблоны, раз нету аналога борландовских пропертей.


Чем принципиально отличаются "борландовские проперти" от аналогов в C#?

246
15 октября 2008 года
GIZMO
1.8K / / 30.07.2004
Цитата: Green
Что именно?
С чем конкретно ты не согласен?



хотя-бы с этим:

Цитата: Green

Видя запись sample.val = 1;
...
Но на самом деле поля такого нет, значение записывается в совершенно иное поле неизвестного типа и ещё не известно какое значение
...



и как видя строчку set_value(1);
ты скажешь, что для нее верно обратное?

3
15 октября 2008 года
Green
4.8K / / 20.01.2000
Цитата: GIZMO
хотя-бы с этим:
и как видя строчку set_value(1);
ты скажешь, что для нее верно обратное?


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

А ты видя к примеру такую строчку:

 
Код:
int size = sizeof(s.Value);

что можешь сказать?
5
15 октября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: flat
Чем принципиально отличаются "борландовские проперти" от аналогов в C#?


Имею в виду борландовские расширения C++ для поддержки свойств. Это было сделано для совместимости с Delphi, в которой свойства существовали изначально. В C# свойства приехали также из Delphi.

4.3K
15 октября 2008 года
flat
142 / / 27.12.2005
Цитата: hardcase
Имею в виду борландовские расширения C++ для поддержки свойств. Это было сделано для совместимости с Delphi, в которой свойства существовали изначально. В C# свойства приехали также из Delphi.


Я понимаю, что ты имеешь ввиду. Не понял только, что именно ты назвал кошмаром. Свойства вообще? Или, как частный случай, свойства в С++? Если свойства в С++ - кошмар, то являются ли они кошмаром в С#? Если нет, то, следовательно, С#-свойства чем-то лучше. Вот я и хочу выяснить, чем в С# свойства лучше по сравнению с их реализацией в C++?

5
15 октября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: flat
Я понимаю, что ты имеешь ввиду. Не понял только, что именно ты назвал кошмаром.

Я называю кошмаром реализацию свойств в C++ через шаблоны. Читать подобный код - не для моих усталых глаз и расшатанных нервов :)

З.Ы. а читать стоит внимательнее - я четко пояснил что я чем считаю еще в том посте.

5.3K
15 октября 2008 года
!Волк
95 / / 19.07.2006
Green и oxotnik333, спасибо за помощь. Удалось в итоге скомпилировать и под MVisual 2005 и под Builder 4, 6. Правда пришлось все таки передавать указатель на метод в качестве параметра конструктора. Иначе Builder старых версий отказывается компилировать.

Цитата: hardcase
Нда. Кошмар.

Свойства - клевая штука, но это заявление не имеет отношения к C++.
Уж лучше геттеры-сеттеры, чем черте какой ужас через шаблоны, раз нету аналога борландовских пропертей.



Свойства пишутся один раз, а потом можно перенести их куда нить в библиотечный файл и забыть. Зато в отличии от свойств Builder'a ты получаешь хоть какую то переносимость кода.

240
16 октября 2008 года
aks
2.5K / / 14.07.2006
Цитата: !Волк
получаешь хоть какую то переносимость кода.


И запутанность.

5.3K
16 октября 2008 года
!Волк
95 / / 19.07.2006
Цитата: aks
И запутанность.


У тебя вызовет непонимание такая строчка в описании класса?

 
Код:
property_write_only_t<sample_t, int> val;

Из названия понятно, что это свойство и применять его можно только для записи. Можно также догадаться, что свойство принимает тип int.
Эта строчка запутает человека, который не знаком с таким понятием, как свойства класса. Но, например начинающие программисты не знают, что такое class. Может тогда вообще перейти от ООП к процедурному программированию?
240
16 октября 2008 года
aks
2.5K / / 14.07.2006
Непонимания не вызовет, но код запутывает. Причем без нужды. В том месте где все могло бы быть прозрачно, без нужды появляется во первых конструкция от которой по внешнему виду ждешь другого поведения, а во вторых даже знаяя, что это свойство, требующее лишних усилий на то, чтобы в нее вникнуть. Это не есть хорошо, тут я полностью солидарен с Грином.
246
16 октября 2008 года
GIZMO
1.8K / / 30.07.2004
Цитата: Green
Да, для неё верно обратное.
Я вижу, что это не поле, а метод класса, а по названию определяю, что он устанавливает некоторое значение.
При этом достаточно заглянуть внутрь этого метода (если не достаточно названия), чтоб понять какое значение и как устанавливается.
Т.о. цепочка раскручивается значительно проще и быстрее, нежели со "свойствами", которые по сути на этот подобные методы накручивают дополнительных и ненужных, а в некоторых случаях вредных "украшательств".


Ничего "быстрее не раскручивается" чтобы воспользоваться св-вом (методом) надо:
а) смотреть хелп
или
б) описание класса (реализацию методов при необходимости)
а свойствами пользоваться удобней, за тебя методы чтения/записи просто вызовет компиллер. "Информативность" названия
сомнительное преймущество, ну на крайняк я могу назвать св-во RWVal, RVal - чтение запись, только чтение и т.д.
Если ты попытаешься (не изучив описание класса) воспользоваться св-во через ж..., то компиллятор совершенно четко объяснит тебе в чем ты не прав (не такой уж он и тупой).

3
16 октября 2008 года
Green
4.8K / / 20.01.2000
Цитата: GIZMO

Ничего "быстрее не раскручивается" чтобы воспользоваться св-вом (методом) надо:
а) смотреть хелп
или
б) описание класса (реализацию методов при необходимости)


a) не всегда к классам прилагается "хелп", я не стану каждый раз лазить в хелп, лучший "хелп" - это код (описание класса), я посмотрю, что мне говорит IntelliSense
б) в случае "свойств" надо будет посмотреть и врубиться в реализацию нескольких классов! А зачемвесь этот огород, если все сводится к вызову set_value ?

Цитата: GIZMO

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


Чем удобнее то?
Вот этого я не понимаю.


Цитата: GIZMO

"Информативность" названия
сомнительное преймущество,


Ещё раз: лучший "хелп" - это код.
Текст программы (а тем более на ЯВУ) пишется для человека, а не для машины. Так хзачем к этому тексту для человека прилагать еще один текст для человека?
"Инструкция по использованию инструкций, для тех кто в танке" :D

Поэтому код должен быть по-максимуму информативным, и здесь просто set_value значительно информативнее.

Цитата: GIZMO

ну на крайняк я могу назвать св-во RWVal, RVal - чтение запись, только чтение и т.д.


Ага, нагородить огород, а потом еще "накрйняк" подписать его "это огород для записи". :)

Цитата: GIZMO

Если ты попытаешься (не изучив описание класса) воспользоваться св-во через ж..., то компиллятор совершенно четко объяснит тебе в чем ты не прав (не такой уж он и тупой).


А может и не объяснить (!), а может объяснить но не четко.
Ты считаешь вот это:

 
Код:
error C2664: 'func' : cannot convert parameter 1 from 'property_<proptype,propowner>' to 'int &'

"совершенно четким объяснением" ? :D

Или вот такое:
 
Код:
error C2440: 'initializing' : cannot convert from 'property_write_only_t<owner_t,value_t,set_method_t>' to 'int'
1>        with
1>        [
1>            owner_t=sample_t<double>,
1>            value_t=double,
1>            set_method_t=sample_t<double>::set_value
1>        ]
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

Причем при использовании get/set вообще не возникнет такой ситуации.

И ещё раз, а что на счет вот этого:
 
Код:
int i = sizeof(s.Value);

Что здесь компилятор мне "объяснит"?
Можно привести и др. безбожно бажные моменты.

Т.о. подобные "свойства" не только запутывают код, но и вносят в него трудновыявляемые ошибки!
3
16 октября 2008 года
Green
4.8K / / 20.01.2000
Цитата: !Волк

У тебя вызовет непонимание такая строчка в описании класса?
 
Код:
property_write_only_t<sample_t, int> val;

Из названия понятно, что это свойство и применять его можно только для записи. Можно также догадаться, что свойство принимает тип int.


Из названия можно предположить, но вот чтоб понять, придется перелопатить код класса property_write_only_t. А он будет не маленьким, если его реализовывать хорошо, т.к. те примеры, которые приводились ранее ну уж очень примитивны и слабо используемы.
То, что свойство принимает int можно ТОЛЬКО догадываться, опять же проверить догадку можно только перелопатив код.
Теперь сравни с наглядностью объявления метода:

 
Код:
void set_value(int);

Уже из набора входных и выходных значений однозначно понятно, что метод предназначен ТОЛЬКО для установки значения. Что принимает метод тоже понятно.

Цитата: !Волк

Эта строчка запутает человека, который не знаком с таким понятием, как свойства класса.


Ну я к примеру знаю, что такое и "свойство" и "прокси", но эта строчка меня озадачит, т.к. даже разработчик этого "свойства" не знает толком, как поведет себя эта строчка.
Вот к примеру приведённые выше классы весьма неполные и в следствии этого глючные.

Цитата: !Волк

Но, например начинающие программисты не знают, что такое class. Может тогда вообще перейти от ООП к процедурному программированию?


ООП упрощает разработку и делает код более переиспольуемым.
А вот на счет "свойств" я этого не могу сказать.

5.3K
16 октября 2008 года
!Волк
95 / / 19.07.2006
Green, зачем лезть внутрь каждого класса и смотреть, как там реализована каждая функция или свойство? Чтобы работать с классом, достаточно знать интерфейс класса, для этого достаточно увидеть список функций(или свойств), находящихся в public. ООП подразумевает именно такой способ праграммирования. Если для того, чтобы понять, как работает конкретный класс, необходимо залезть внутрь описания, значит он не правильно спроектирован. При работе например с std::vector ты ведь не лезешь в исходники, чтобы посмотреть, как там и что работает? Тебе важно лишь знать список доступных методов.
И еще я не понимаю, почему при работе с встроенными в компилятор свойствами не у кого не возникает вопросов? В том же Builder'е в любом компоненте присутствуют свойства.


Цитата:
Вот к примеру приведённые выше классы весьма неполные и в следствии этого глючные.


И чего же там не хватает для полноценного использования?

240
16 октября 2008 года
aks
2.5K / / 14.07.2006
Цитата: !Волк
Тебе важно лишь знать список доступных методов.


Вооот. Методы то как раз дают прозрачный интерфейс, а вот свойства в том виде как приводятся здесь - нет.

Цитата: !Волк

И еще я не понимаю, почему при работе с встроенными в компилятор свойствами не у кого не возникает вопросов?


А какие тут могут быть еще вопросы? Зачем использовать неудобный и не переносимый костыль? Так это даже задумываться не надо. )

1
16 октября 2008 года
kot_
7.3K / / 20.01.2000
"Свойства" как правило - это большое зло. И если их использование в компонентах Делфи(Билдера) оправдано общей архитектурой библиотеки - кстати на счет существования изначальных свойств в делфи - это реализация борландовского компилятора и от делфи/билдера не очень зависит - то остальным разработчикам стоит не повторять ошибок. Просто разработчики компании решили что это есть неплохая идея - и ввели расширение в реализацию языка.
Ну а в целом идея бредовая и в первою очередь выгодна проприетарным разработчикам - потому как именно со свойствами - нужна справка, примеры и прочиие - потому как из кода понять что творится не возможно.
5.3K
16 октября 2008 года
!Волк
95 / / 19.07.2006
Цитата: aks

А какие тут могут быть еще вопросы? Зачем использовать неудобный и не переносимый костыль? Так это даже задумываться не надо. )


Нет, я имел ввиду не использование в своих классах, а то, что компоненты Builder'a включают свойства, как часть интерфейса и приходится их использовать. При этом никто не жалуется на интерфейс их компонентов.

3
16 октября 2008 года
Green
4.8K / / 20.01.2000
Цитата: !Волк

Green, зачем лезть внутрь каждого класса и смотреть, как там реализована каждая функция или свойство?


Ты прав, (почти) не нужно. Но вот c этими "свойствами" придется!

Цитата: !Волк

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


Вот как раз со свойствами будет не достаточно. Я по вот этому:

 
Код:
property_write_only_t<sample_t, int> val;

не скажу ТОЧНО, как "работать с классом", т.к. не получу исчерпывающую инф. о его интерфейсе.
Более того, я запутаюсь, т.к. на видимое сходство "свойства" с обычным полем класса, оно таковым не является и компилятор мне здесь не помощник, т.к. такого рода ошибок (например, уже указанный sizeof(s.Value) ) он не выявит.

Цитата: !Волк

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


Угу, согласен. Поэтому класс со "свойствами" спроектирован не правильно.

Цитата: !Волк

При работе например с std::vector ты ведь не лезешь в исходники, чтобы посмотреть, как там и что работает? Тебе важно лишь знать список доступных методов.


Правильно. Потому что в отличие от "свойств", методы дают полную информацию об интерфейсе.

Цитата: !Волк

И еще я не понимаю, почему при работе с встроенными в компилятор свойствами не у кого не возникает вопросов? В том же Builder'е в любом компоненте присутствуют свойства.


У меня не возникает, т.к. я их НЕ ИСПОЛЬЗУЮ, и никому не советую. :)
Да и уже говорил: "горе-компиляторы" мы не рассматриваем. :)

Цитата: !Волк

И чего же там не хватает для полноценного использования?



Да много чего, очень много.
Пара примеров:

 
Код:
cin >> s.val;

s.val++;

продолжать, как понимаешь, можно долго.
Некоторые вещи вообще реализовать будет невозможно.
5.3K
16 октября 2008 года
!Волк
95 / / 19.07.2006
Ладно, переубедили.))
Я сторонник стабильного кода и любые неопределенности, которые могут приводить к ошибкам, я стараюсь избегать.)
Вообще меня обычные свойства мало интересовали. Большой интерес вызывали индексированные свойства, а точнее свойства с двойным индексом. Дело в том, что мне понадобилось написать класс "таблица" и класс "матрица". При обращении к ячейкам соответствующих классов предполагалось вызывать методы
 
Код:
void read_cell(T& a_cell, const int a_col, const int a_row);
void write_cell(const T& a_cell, const int col, const int row);

Но работая с Builder и используя компонент TStringGrid(таблица строк), в котором обращение к ячейкам происходило посредством свойства
 
Код:
Cells[Col][Row]

очень захотелось реализовать в своих классах подобное.
Запись вида
 
Код:
table.cells[1][2] = 5;
мне казалась красивее, чем такая
 
Код:
table.write_cell(5, 1, 2);

Но, раз уж это приводит к потенциальным ошибкам, я от этого откажусь)

Спасибо всем за помощь.
3
17 октября 2008 года
Green
4.8K / / 20.01.2000
Цитата: !Волк

очень захотелось реализовать в своих классах подобное.
Запись вида
 
Код:
table.cells[1][2] = 5;


Но, раз уж это приводит к потенциальным ошибкам, я от этого откажусь)


Так а при чем тут "свойства"? Они здесь вообще никаким боком.
Здесь просто operator[].

Можно это организовать с помощью vector<vector>:
http://forum.codenet.ru/showpost.php?p=222574&postcount=4

Если убрать транспонирование, то всё выглядит совсем просто:

Код:
template<typename T>
class Matrix
{
public:
    Matrix(unsigned int width, unsigned int height)
        :array(width, std::vector<T>(height)) {}

    std::vector<T>& operator[](unsigned int row) { return array[row]; }
    const std::vector<T>& operator[](unsigned int row) const { return array[row]; }

private:
    std::vector< std::vector<T> > array;
};

IMHO все просто и прозрачно.
1
17 октября 2008 года
kot_
7.3K / / 20.01.2000
тут судя по всему у автора присутствует некоторая путаница собственно __property - и поля и функции класса. Что как раз хорошо иллюстрирует вредность данного подхода - как для афтара так и всем остальным. :)
5.3K
17 октября 2008 года
!Волк
95 / / 19.07.2006
Ну у меня до этого было реализовано через перегрузку операторов "[]". Думал, через свойства удобнее будет.
В предыдущем моем примере запись вида
 
Код:
table.cells[1][2] = 5;
с помощью обычной перегрузки операторов "[]" не реализовать, в отличии от такой записи
 
Код:
table[1][2] = 5;

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

Кстате, я предпочитаю использовать в качестве таблицы просто
 
Код:
vector<T>
вместо
 
Код:
vector<vector<T> >
Меня жаба давит, что тратится память на хранение размера каждого столбца, хотя они все одинаковые.:)
240
17 октября 2008 года
aks
2.5K / / 14.07.2006
Цитата: !Волк

В предыдущем моем примере запись вида
 
Код:
table.cells[1][2] = 5;
с помощью обычной перегрузки операторов "[]" не реализовать, в отличии от такой записи
 
Код:
table[1][2] = 5;

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



table.getSomeData()[1][2] = 5;

getSomeData() - возвращает ссылку на нужную данную. Константную или обычную, в зависимости от требовния. )
В чем разница, только в наличии круглых скобочек?

5.3K
17 октября 2008 года
!Волк
95 / / 19.07.2006
Цитата: aks
table.getSomeData()[1][2] = 5;
В чем разница, только в наличии круглых скобочек?


Это портит всю красоту:)
Кроме того, это для каждого данного придется вводить оператор "[]". А если он там уже есть, но мне нужно по другому интерпретировать индекс, то придется вообще пронаследовать и переопределить этот оператор. Это требует немного больше затрат по времени, чем написание методов set, get для каждого данного.

240
17 октября 2008 года
aks
2.5K / / 14.07.2006
Не понял, а со свойствами, что не предется оператор [] для каждой данной п ереопределять? В чем отличие то? )
Только в скобочках. Темболее если данные будет однотианые, то и переопределять для каждой не предется.
5.3K
17 октября 2008 года
!Волк
95 / / 19.07.2006
Цитата: aks
Не понял, а со свойствами, что не предется оператор [] для каждой данной п ереопределять? В чем отличие то? )
Только в скобочках. Темболее если данные будет однотианые, то и переопределять для каждой не предется.



Можно сделать сервис индексов и подставлять уже готовые индексированные свойства.
Вот пример такого свойства.

Код:
// Свойство только для записи с двумя индексами
template<class owner_t, class value_t>
struct domen_write_only_dual_index_t
{
  typedef void (owner_t::*set_method_t) (const int, const int, const value_t&);

  template<set_method_t set_method>
  class property_write_only_t
 {
    owner_t& m_owner;
    int m_index1;
    int m_index2;
  public:
    property_write_only_t(owner_t& a_owner) :
    m_owner(a_owner), m_index1(0), m_index2(0)
    {}
    inline const value_t&  operator = (const value_t& a_value)
    {
      (m_owner.*set_method)(m_index1, m_index2, a_value);
      return a_value);
    }
    inline void set_index(const int a_index1, const int a_index2)
    {
     m_index1 = a_index1;
     m_index2 = a_index2;
    }
  };

  template<set_method_t set_method>
  class property_write_only_index2_t   
  {
  public:
  private:
    owner_t& m_owner;
    property_write_only_t<set_method> m_property_write_only;
    int m_index1;
  public:
    property_write_only_index2_t(owner_t& a_owner) :
    m_owner(a_owner),
    m_property_write_only(a_owner),
    m_index1(0)
    {
    }
    void set_index(const int a_index1)
    {
      m_index1 = a_index1;
    }
    property_write_only_t<set_method> operator[](const int a_index2)
    {
      m_property_write_only.set_index(m_index1, a_index2);
      return m_property_write_only;
    }
  };

  template<set_method_t set_method>
  class property_write_only_index1_t
  {
  private:
    owner_t& m_owner;
    property_write_only_index2_t<set_method> m_property_write_only_index2;
  public:
    property_write_only_index1_t(owner_t& a_owner) :
    m_owner(a_owner),
    m_property_write_only_index2(a_owner)
    {
    }
    property_write_only_index2_t<set_method> operator[](const int a_index2)
    {
      m_property_write_only_index2.set_index(a_index2);
      return m_property_write_only_index2;
    }
  };
  typedef property_write_only_index1_t property_t;
};


Только это свойство не работает для шаблонных методов. Но можно сделать чтобы работало. Суть от этого не изменится.
У меня были реализованы свойства с одним индексом, с двумя и без индексов. В итоге, для того, чтобы включить в какой либо класс доступ к данным через свойство, нужно было описать фунци set, get с необходимым количеством индексов и инициализировать ими свойство.
246
17 октября 2008 года
GIZMO
1.8K / / 30.07.2004
Цитата: Green
a) не всегда к классам прилагается "хелп", я не стану каждый раз лазить в хелп, лучший "хелп" - это код (описание класса), я посмотрю, что мне говорит IntelliSense


Гы-ы, странный однака товариЩ:) Я не утверждал, что хелп поставляется - всегда и в него обязательно надо лазить. Слово - или ты не понимаешь? Может тебе по-арабски написать?
Т.е если бы я заявлял - "Только по хелпу можно понять, что есть данное св-во и как его использовать!", то тогда п. а) можно как-то понять...

Цитата: Green

б) в случае "свойств" надо будет посмотреть и врубиться в реализацию нескольких классов! А зачемвесь этот огород, если все сводится к вызову set_value ?


С какого перепугу "врубаться" вот мне например пофигу смотреть определение/реализацию св-ва или метода при чем пофигу где в исходниках или справке.
А эта странная фраза - "нескольких классов"? т.е. у тебя никогда не бывает базовых классов?

Цитата: Green

Чем удобнее то?
Вот этого я не понимаю.


Obj.set_value(1);
Obj.value=1;
кароче на 5 символов:)


Цитата: Green

Ещё раз: лучший "хелп" - это код.
Текст программы (а тем более на ЯВУ) пишется для человека, а не для машины.


еще два: я не утверждал обратного, и хелп и код полезны

Цитата: Green

Так хзачем к этому тексту для человека прилагать еще один текст для человека?
"Инструкция по использованию инструкций, для тех кто в танке" :D
Поэтому код должен быть по-максимуму информативным, и здесь просто set_value значительно информативнее.


ну встречаются индивидуумы которые и справкой пользоваться не умеют, а set_value ничем не информативней...

ЗЫ: спасибо за лояльность только при чем тут она и по отношению к кому:)?

3
17 октября 2008 года
Green
4.8K / / 20.01.2000
Цитата: GIZMO

Гы-ы, странный однака товариЩ:) Я не утверждал, что хелп поставляется - всегда и в него обязательно надо лазить.
Т.е если бы я заявлял - "Только по хелпу можно понять, что есть данное св-во и как его использовать!", то тогда п. а) можно как-то понять...


Но ты назвал его одним из пунктов, и я ответил тебе по этому пункту.

Цитата: GIZMO

Слово - или ты не понимаешь? Может тебе по-арабски написать?


Может тебя в бан отправить?

Цитата: GIZMO

С какого перепугу "врубаться" вот мне например пофигу смотреть определение/реализацию св-ва или метода при чем пофигу где в исходниках или справке.


Да я вижу, тебе вообще все пофигу...
С какого перепугу, я уже написал несколько раз (см. примеры, в т.ч. и результаты компиляции), только ты врубиться не смог, поэтому по-тихому и слил.

Цитата: GIZMO

А эта странная фраза - "нескольких классов"? т.е. у тебя никогда не бывает базовых классов?


При чем тут базовые классы?
Где и сколько "базовых классов" у метода set_value?

Цитата: GIZMO

Obj.set_value(1);
Obj.value=1;
кароче на 5 символов:)


М-да...
Идиотская улыбка показывает идиотизм твоего примера?
Это самый весомый твой аргумент в защиту "удобства" :D
В противовес всем тем вменяемым и обоснованным аргументам, которые привели другие участники обсуждения?
Тогда ты все удачно слил...

Цитата: GIZMO

ну встречаются индивидуумы которые и справкой пользоваться не умеют, а set_value ничем не информативней...


Ну для тех кому "пофиг" точно не информативней.
Впрочем, после твоего "шедевра" с примером "удобства"... информативностью является количество букв? :D

Цитата: GIZMO

ЗЫ: спасибо за лояльность только при чем тут она и по отношению к кому?


Пожалуйста, обращайтесь ещё.
За лояльность к мнению других.
P.S. Если твои сообщения не начнут носить информативный характер, мне придется их удалить, начиная с первого.

1
17 октября 2008 года
kot_
7.3K / / 20.01.2000
Цитата: GIZMO
<...skipped...>


чет тебя понесло?
Если свойства так уж милы сердцу - то желательно приводить более весомые аргументы, чем количество букв.
тем более это твои слова:

Цитата:

чтобы воспользоваться св-вом (методом) надо:
а) смотреть хелп
или
б) описание класса (реализацию методов при необходимости)



Цитата:

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


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

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог