Свойства в С++
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 20.11.01 00:25
Оценка: 525 (20)
Статья:
Свойства в С++
Автор(ы): Денис Майдыковский

В этой статье автор рассматривает различные способы реализации свойств в
стиле Visual Basic на C++. Некоторые способы специфичны для Visual C++,
тогда как другие годятся для применения в любой программе, написанной на
языке C++.


Авторы:
Денис Майдыковский

Аннотация:
В этой статье автор рассматривает различные способы реализации свойств в стиле Visual Basic на C++. Некоторые способы специфичны для Visual C++, тогда как другие годятся для применения в любой программе, написанной на языке C++.
А как же ссылки?
От: null  
Дата: 16.09.02 17:29
Оценка:
А зачем нужны такие сложности... Вроде бы с помощью указателей превосходно получается...
/*.............*/
class A
{
int i;
public:
int get();{return i;}
int& put(); {reurn i;}
};
int main()
{

A x;

x.put()=1;

}
/*..............*/
Разделение по способам доступа
От: KA it-knowledge-base.blogspot.com
Дата: 26.04.02 07:17
Оценка:
Было бы лучше ввести разные шаблоны для свойств только для чтения, только для записи, ...
//
#import <windows.bas>
class IWindows9x:protected DOS { private: virtual HANDLE EnumClouds()=0; };
мысль
От: rounin  
Дата: 29.01.02 02:50
Оценка:
get- и set-методы можно сделать аргументами шаблона.
Тогда размер свойства уменьшится в 3раза.
Хотя количество классов возрастёт :(

template <typename proptype, typename propowner,
proptype (propowner::*getmethod)(),
void (propowner::*setmethod)(proptype)>
class property {...};

...
property<int, CValue, &get_Value, &put_Value> Value;
?
От: neXt  
Дата: 28.11.01 04:31
Оценка:
а как тогда реализуется свойства с параметром
вроде List->Items[1] = ...
Достойно
От: neXt  
Дата: 22.11.01 03:03
Оценка:
Очень интересная статья!
От: boombastik  
Дата: 21.11.01 00:25
Оценка:
Мое почтение!
С уважением, Владимир
Re: А как же ссылки?
От: Aquary Россия https://wmspanel.com/
Дата: 01.10.02 02:10
Оценка:
Тогда не проще ли вообще сделать public int i?
https://wmspanel.com/nimble — Nimble Streamer media server for live and VOD HLS, RTMP, HTTP streaming
https://wmspanel.com/ — Control and reporting panel for Wowza and Nimble Streamer
http://scm-notes.blogspot.com/ — Блог об управлении конфигурацией
Re: ?
От: RailRoader Украина  
Дата: 26.02.02 10:31
Оценка:
Перегрузить оператор [].
А также можно *, ->, () и получить кучу фантастических вещей :)
Re: ?
От: Аноним  
Дата: 07.07.03 13:22
Оценка: -1 :)
Здравствуйте, neXt, Вы писали:

X>а как тогда реализуется свойства с параметром

X>вроде List->Items[1] = ...

Дык объяви массив свойств
Re: Свойства в С++
От: jazzer Россия Skype: enerjazzer
Дата: 07.07.03 14:36
Оценка:
Здравствуйте, Денис Майдыковский, Вы писали:

ДМ>Статья:

ДМ>Свойства в С++

ДМ>Авторы:

ДМ> Денис Майдыковский

ДМ>Аннотация:

ДМ>В этой статье автор рассматривает различные способы реализации свойств в стиле Visual Basic на C++. Некоторые способы специфичны для Visual C++, тогда как другие годятся для применения в любой программе, написанной на языке C++.


Помимо operator=, нужно еще много чего перегружать, например, инкременты

Но это мы оставим пытливому читателю в качестве упражнения
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: А реально кто ни будь использует ТАКИЕ свойства?
От: SergeyBi  
Дата: 07.07.03 17:15
Оценка:
Отзовитесь пожалуйста. Неужели при таких недостатках:

//==================
При каждом обращении к "свойству" происходит два вызова функции.

Использование таких "свойств" требует дополнительных затрат памяти из-за того, что на каждое "свойство" требуется 3 дополнительных указателя, что составляет 12 байт накладных расходов.

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

Для каждого "свойства" необходимо не забыть произвести инициализацию в конструкторе класса-владельца.

//==================

достоинства иногда побеждают? И какие достоинства вообще существуют кроме наглядности?
Re[2]: А реально кто ни будь использует ТАКИЕ свойства?
От: Аноним  
Дата: 08.07.03 05:40
Оценка: +2
Здравствуйте, SergeyBi, Вы писали:

SB>Отзовитесь пожалуйста. Неужели при таких недостатках:


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

В некотором классе была объявлена открытая переменная, которой присваивалось значение в различных местах
программы. Естественно, рано или поздно, "бомба взорвалась" и потребовалось производить некие дейсвия
при изменении этой переменной. Прежде чем "перелопачивать" всесь вызывающий код было эта переменная
была преобразована в "свойство", что позволило отладить логику самого класса, а уже позже, спокойно
обрабатывать вызовы.

Денис
Re[3]: тогда такой вопрос...
От: SergeyBi  
Дата: 08.07.03 06:11
Оценка:
Используете ли Вы такие свойства ТОЛЬКО ради наглядности?
Re[4]: тогда такой вопрос...
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 08.07.03 06:19
Оценка:
Здравствуйте, SergeyBi, Вы писали:

SB>Используете ли Вы такие свойства ТОЛЬКО ради наглядности?


В реальных проектах нет.
А на этапе обучения вполне можно, особенно для тех кто с VB переползает.
Re[2]: А реально кто ни будь использует ТАКИЕ свойства?
От: Awaken Украина  
Дата: 08.07.03 09:35
Оценка:
SB>достоинства иногда побеждают? И какие достоинства вообще существуют кроме наглядности?

бывает нужно разделить операцию присваивания для левого и правого оператора на 2 разных
метода.
Re[3]: А реально кто ни будь использует ТАКИЕ свойства?
От: jazzer Россия Skype: enerjazzer
Дата: 08.07.03 10:13
Оценка:
Здравствуйте, Денис, Вы писали:

А>В некотором классе была объявлена открытая переменная, которой присваивалось значение в различных местах

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

хотя лучше purify для этого использовать
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: мысль
От: Sergeem Израиль  
Дата: 08.07.03 10:39
Оценка:
Здравствуйте, rounin, Вы писали:

R>get- и set-методы можно сделать аргументами шаблона.

R>Тогда размер свойства уменьшится в 3раза.
R>Хотя количество классов возрастёт

ну и пусть растет. все равно весь код — inline!
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Re: вот как делал я..
От: PK Sly http://www.vocord.ru/
Дата: 22.03.04 10:37
Оценка:
#define PROPERTY(OWNERNAME, TYPE, NAME, FNGET, FNPUT) \
struct propclass_##NAME { \
    inline operator TYPE() { \
        CONTAINING_RECORD(this, OWNERNAME, NAME)->FNGET(); \
    } \
    inline void operator=(TYPE src) { \
        CONTAINING_RECORD(this, OWNERNAME, NAME)->FNPUT(src); \
    } \
} NAME;

#define PROPERTY_DEF(OWNERNAME, TYPE, NAME) \
    PROPERTY(OWNERNAME, TYPE, NAME, Get_##NAME, Put_##NAME)

использование этого:
    class C
    {
    public:
        int Get_i() { cout << "Get = 1" << endl; return 1; }
        void Put_i(int n) { cout << "Put(" << n << ')' << endl; }
        PROPERTY_DEF(C, int, i);
    };

    C c;
    cout << c.i << endl;
    c.i = 1;

Понятно, что для нормальной работы надо ещё добавить все возможные операторы (типа ++, += и т.д.) и сделать дополнительно обёртку для классов с оператором -> и т.п.

Наверняка кто-то скажет про нехорошесть использования макросов вообще, а особенно CONTAINING_RECORD... но посмотрите окончание статьи, где описаны недостатки. Ни одного из тех недостатков тут нет. что и требовалось...
VAX/VMS rulez!
Re: Свойства в С++
От: Аноним  
Дата: 22.03.04 11:59
Оценка:
Здравствуйте, Денис Майдыковский, Вы писали:

ДМ>Статья:



ДМ>Авторы:

ДМ> Денис Майдыковский

ДМ>Аннотация:

ДМ>В этой статье автор рассматривает различные способы реализации свойств в стиле Visual Basic на C++. Некоторые способы специфичны для Visual C++, тогда как другие годятся для применения в любой программе, написанной на языке C++.

Не пойму смысл данной конструкции. Объясните что это
typedef proptype (propowner::*getter)();
Re[2]: Свойства в С++
От: jazzer Россия Skype: enerjazzer
Дата: 22.03.04 12:00
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Денис Майдыковский, Вы писали:


ДМ>>Статья:



ДМ>>Авторы:

ДМ>> Денис Майдыковский

ДМ>>Аннотация:

ДМ>>В этой статье автор рассматривает различные способы реализации свойств в стиле Visual Basic на C++. Некоторые способы специфичны для Visual C++, тогда как другие годятся для применения в любой программе, написанной на языке C++.

А>Не пойму смысл данной конструкции. Объясните что это

А>typedef proptype (propowner::*getter)();

читай про указатели на члены
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Свойства в С++
От: achp  
Дата: 22.03.04 12:03
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Не пойму смысл данной конструкции. Объясните что это

А>typedef proptype (propowner::*getter)();

Объявляется имя getter для типа "указатель на функцию-член класса propowner, не имеющую параметров и имеющую типом возвращаемого значения proptype."
Да здравствует ИМХО!
Re[2]: даааа...
От: PK Sly http://www.vocord.ru/
Дата: 22.03.04 12:06
Оценка:
Ей богу, не для этого тему поднимал. Простите, пожалуйста..
VAX/VMS rulez!
Re[2]: А реально кто ни будь использует ТАКИЕ свойства?
От: Аноним  
Дата: 10.07.04 01:32
Оценка:
Здравствуйте, SergeyBi, Вы писали:

SB>Использование шаблонов приводит к увеличению размеров исполняемого кода, поскольку компилятор будет генерировать отдельный класс для каждой пары "proptype" и "propowner".


Я чего-то не понимаю. Я думал, генерируются только те классы, которые надо?

Неужели если имеем например 100 классов, генерируется 10.000 классов для всех возможных пар?
Re: мысль
От: Atomic Max Россия  
Дата: 17.02.05 16:26
Оценка:
R>get- и set-методы можно сделать аргументами шаблона.
R>Тогда размер свойства уменьшится в 3раза.

Да, такая идея интересна, так как использует статическое программирование на этапе компиляции. Если методы доступа известны на этапе компиляции, то зачем это делать во время выполнения (передавать указатели при каждом конструировании). Так что, я полностью согласен с предыдущим оратором.

Но я озадачился другим. Можно ли не хранить вообще никаких дополнительных указателей? То есть может ли класс свойства самостоятельно вычислить указатель на класс-носитель свойства. Эта задача (применительно к подходу из статьи) эквивалентна задаче восстановления указателя на объемлющий объект-композит. То есть если у нас есть композит A, то его поле данных типа B может восстановить указатель на свой контейнер (при условии знания структуры А):

class A
{
public:
  class B
  {
  public:
    inline A * Container() 
    {
      // вычисляем смещение поля b_ внутри A
      B A::*pB = &A::b;
      // базируемся относительно своего this
      return (A*) ( size_t(this) - *((size_t *)&pB) );
    }
    //...
  }
  B b_;
  //...
}

A a;
cout << ( & A == A.b_.Container() );


Очевилно, что это вычисление не статическое и происходит во время выполнения программы.

У меня вопрос к аудитории:
Можно ли более элегантно решить именно такую задачу?
Re[2]: мысль
От: Alexey Chen Чили  
Дата: 17.02.05 22:06
Оценка:
Здравствуйте, Atomic Max, Вы писали:

AM> B A::*pB = &A::b;

AM> // базируемся относительно своего this
AM> return (A*) ( size_t(this) — *((size_t *)&pB) );

AM>У меня вопрос к аудитории:

AM>Можно ли более элегантно решить именно такую задачу?

Подсказка: зачем тебе указатель на реальный обьект, если с данными лежащими по этому указателю ты не работаешь?
Re[2]: мысль
От: _Winnie Россия C++.freerun
Дата: 18.02.05 04:19
Оценка: 2 (1) +1
Здравствуйте, Atomic Max, Вы писали:

AM>Но я озадачился другим. Можно ли не хранить вообще никаких дополнительных указателей?



//----------------------------------------------------------------------
//да, property без изменения бинарной раскладки класса 
//вызов через указатель на член убивает оптимизирующий компилятор.
//VS2003 распознает эти property в IntelliSense 

//сразу возникает вопрос, как разрулить это - 
//T Owner::GetX() const
//T Owner::GetX() const volatile
//T Owner::GetX() volatile
//Owner::x
//T Owner::GetX() 
//T &Owner::GetX() 
//мне кажется, что это можно сделать через 
//sizeof(overloaded_function(MakeT())) трюк, но мне лень это проверять

//тут еще подводные камни с константностью функции NAME(), 
//без парочки const_cast видимо не обойдется, если доводить до ума.

template <
  class Owner, 
  class PropT, 
  void (Owner::*Setter)(PropT), 
  PropT (Owner::*Getter)()>
struct Property
{
  Owner &owner;
  Property(Owner &owner): owner(owner) {};
  //да, void. Не хочу мозг парить.
  void operator =(const PropT &x) { (owner .* Setter)(x); }
  operator const PropT () { return (owner .* Getter)(); }
};

//можно сделать PROPERTY_RW, PROPERTY_R, PROPERTY_W, 

#define PROPERTY(NAME, Owner, T, Setter, Getter)\
Property<Owner, T, &Owner::Setter, &Owner::Getter> NAME() \
{ \
  return Property<Owner, T, &Owner::Setter, &Owner::Getter>(*this);\
}

//----------------------------------------------------------------------


#include <fstream>
#include <iostream>
#include <string>

struct MegaClass
{
private:
  int GetFromFile()
  {
    int i;
    std::ifstream f("config.txt");
    f >> i;
    return i*2;
  }

  void SetValueInFile(int i)
  {
    std::ofstream f("config.txt");
    f << i;
  }

  std::string GetS() { return "hello"; }
  void SetS(std::string sss) { std::cout <<sss; }

public:


  PROPERTY(X, MegaClass, int, SetValueInFile, GetFromFile);
  PROPERTY(Y, MegaClass, int, SetValueInFile, GetFromFile);
  PROPERTY(Sss, MegaClass, std::string, SetS, GetS);


  MegaClass()
  {
    this->X() = 0;
  }
  
};


volatile int i;


class Test2
{
private:
  void SetI(int i) { ::i = i; } 
  int GetI() { return ::i; }
public:
  PROPERTY(I, Test2, int, SetI, GetI);
};


int main()
{
  std::cout <<sizeof(MegaClass) <<"\n"; //empty class

  MegaClass mc;
  mc.X() = 10;
  int i = mc.Y();

  std::string s = mc.Sss();
  mc.Sss() = "world";

  //проверяю в листинге на asm, что компилятор уничтожает лишние вызовы.
  Test2 t;
  t.I() = 10;
  i = t.I();

  std::cout <<i;
}
Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: мысль
От: Atomic Max Россия  
Дата: 18.02.05 14:45
Оценка:
Здравствуйте, Alexey Chen, Вы писали:

AC>Подсказка: зачем тебе указатель на реальный обьект, если с данными лежащими по этому указателю ты не работаешь?


Видимо, я не понял подсказку. Поясните, пожалуйста.

Да, я не обращаюсь к полям данных на прямую, но я должен вызывать методы объемлющего объекта (реализация "свойства" в контексте обсуждаемой статьи). А по моим сведениям, я не могу вызвать нестатический метод объекта, не имея в распоряжении указателя на сам объект.
Re[3]: мысль
От: Atomic Max Россия  
Дата: 18.02.05 15:54
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>

_W>int main()
_W>{
_W>  std::cout <<sizeof(MegaClass) <<"\n"; //empty class

_W>  MegaClass mc;
_W>  mc.X() = 10;
_W>  int i = mc.Y();

_W>  std::string s = mc.Sss();
_W>  mc.Sss() = "world";

_W>  //проверяю в листинге на asm, что компилятор уничтожает лишние вызовы.
_W>  Test2 t;
_W>  t.I() = 10;
_W>  i = t.I();

_W>  std::cout <<i;
_W>}

_W>


Да, идея интересная. Только "свойство" превратилось из поля класса в метод, поэтому надо писать пустые скобки. Интересно, что раньше, реализуя "свойство" через поле данных, я перегружал оператор () так, чтобы он возвращал результат Get-метода. Таким образом у меня появлялась возможность вызывать константные методы оригинального поля данных объекта. Например:
  //...
  const PropT operator () () { return (owner .* Getter)(); }
  //...

Теперь же придётся писать два раза скобки, чтобы спросить у строки длину :
//...
  cout << "Length is " << ms.Sss()().length() << endl;
//...
Re[4]: мысль
От: Alexey Chen Чили  
Дата: 18.02.05 18:27
Оценка: 1 (1)
Здравствуйте, Atomic Max, Вы писали:

AC>>Подсказка: зачем тебе указатель на реальный обьект, если с данными лежащими по этому указателю ты не работаешь?

AM>Видимо, я не понял подсказку. Поясните, пожалуйста.

Вот пример. Хоть он и не так изыскан как решения на шаблонах

#include <stdio.h>

#define PROPERTY(T,__type,__set,__get,__name) \
  \
  __type value() const { return resolve_(this,1)->__get(); } \
  \
  __type operator+() const { return value(); } \
  \
  operator __type () const { return value(); } \
  \
  void \
    operator = (__type const& a) { resolve_(this,1)->__set(a); } \
  \
  template <class fake> static T* resolve_(const void* p,fake) {\
    T* _ = 0; \
    return (T*)( (char*)p - ( (char*)(&_->__name) - (char*)(_) ) );\
  } 


struct Obj1 
{
  void SetP1(int a) { printf("SetP1(%d)\n",a); }
  int  GetP1() const { printf("GetP1()\n"); return 0; }
  void SetP2(int a) { printf("SetP2(%d)\n",a); }
  int  GetP2() const { printf("GetP2()\n"); return 0; }
  //union { ещё одна причина не любить gcc, 
    struct __Property_a { PROPERTY(Obj1,int,SetP1,GetP1,a) } a;
    struct __Property_b { PROPERTY(Obj1,int,SetP2,GetP2,b) } b;
  //};
};

int main ()
{
  Obj1 o;
  printf("sizeof(Obj1) = %d\n",sizeof(Obj1));
  o.a = 1;
  printf("o.a + 1 = %d\n", o.a + 1);
  o.b = 0;
  printf("o.b + 1 = %d\n", o.b + 1);
  return 0;
}
Re[3]: А реально кто ни будь использует ТАКИЕ свойства?
От: remark Россия http://www.1024cores.net/
Дата: 03.09.06 08:16
Оценка:
Здравствуйте, Awaken, Вы писали:


SB>>достоинства иногда побеждают? И какие достоинства вообще существуют кроме наглядности?


A>бывает нужно разделить операцию присваивания для левого и правого оператора на 2 разных

A>метода.


Левый и правый оператор присваивания???



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: А реально кто ни будь использует ТАКИЕ свойства?
От: Roman Odaisky Украина  
Дата: 03.09.06 11:15
Оценка: :)
Здравствуйте, remark, Вы писали:

R>Левый и правый оператор присваивания???


http://rsdn.ru/Forum/?mid=577485
Автор: PK Sly
Дата: 22.03.04


а ты для чего?
До последнего не верил в пирамиду Лебедева.
Re[5]: А реально кто ни будь использует ТАКИЕ свойства?
От: remark Россия http://www.1024cores.net/
Дата: 03.09.06 20:08
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, remark, Вы писали:


R>>Левый и правый оператор присваивания???


RO>http://rsdn.ru/Forum/?mid=577485
Автор: PK Sly
Дата: 22.03.04


RO>а ты для чего?


здесь
Автор: Doc
Дата: 03.09.06


Получается, что для этого же


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: мысль
От: alno http://blog.alno.name/
Дата: 26.05.08 15:56
Оценка: 2 (1) -1
здесь аналогичное решение, только на смеси макросов и шаблонов.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.