Программирование >>  Перегруженные имена функций и идентификаторы 

1 ... 132 133 134 [ 135 ] 136 137 138 ... 210


int& setA(const int& x); int getA(); public:

/* ... */ a;

...

Test t;

t.a = 10; Вызов Test::setA()

int r = t.a; Вызов Test::getA()

Естественный способ - использовать шаблоны. Например, вот так:

template<class A, class T, T& (A::*setter)(const T&), T (A::*getter)()

>

class property

...

Параметр A - класс, к которому принадлежат функции установки и чтения значения свойств (они передаются через аргументы шаблона setter и getter). Параметр T - тип самого свойства (например, int для предыдущего примера).

На запись, которая используется для описания указателей на функции, стоит обратить внимание - известно, что многие программисты на C++ и не догадываются о том, что можно получить и использовать адрес функции-члена класса. Строго говоря, функция-член ничем не отличается от обычной, за исключением того, что ей требуется один неявный аргумент, который передается ей для определения того объекта класса, для которого она применяется (это указатель this). Таким образом, получение адреса для нее происходит аналогично, а вот использование указателя требует указать, какой конкретно объект используется. Запись A::*foo говорит о том, что это указатель на член класса A и для его использования потребуется объект этого класса.



Теперь непосредственно весь класс целиком:

template<class A, class T, T& (A::*setter)(const T&), T (A::*getter)()

>

class property

protected: A * ptr; public:

property(A* p) : ptr(p) { }

const T& operator= (const T& set) const

assert(setter != 0); return (ptr->*setter)(set);

operator T() const

assert(getter != 0); return (ptr->*getter)();

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

Думаем, что идея предельно ясна. Использование указателей на функцию-член заключается как раз в строках вида:

(ptr->*f)();

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



Использовать класс property надо следующим образом:

class Test

...

property<Test, int, &Test::setA, &Test::getA> a;

Test() : a(this) { }

Компиляторы g++, msvc и bcc32 последних версий спокойно восприняли такое издевательство над собой. Тем не менее, более старые варианты этих же компиляторов могут ругаться на то, что используется незаконченный класс в параметрах шаблона, не понимать того, что берется адрес функций и т.д. Честно говоря, кажется что стандарту это не противоречит.

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

На самом деле, теоретики расширения концепций очень часто забывают то, за что иногда действительно стоит уважать свойства. Это возможность сохранить через них объект и восстановить его (т.е., создать некоторое подобие persistent object). В принципе, добавить такую функциональность можно и в шаблон выше. Как? Это уже другой вопрос

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

Комментарии

Плохое комментирование исходных текстов является одним из самых тяжелых заболеваний программ. Причем программисты



1 ... 132 133 134 [ 135 ] 136 137 138 ... 210

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика