Всем доброго времени суток!
Свойства не реализованы в C ++.То есть мы не можем написать
myObject.property = value; // try to set field f_ to value
, это property
является личным участником данных.Публичные члены данных нарушают правила инкапсуляции ООП.
Вместо этого мы должны написать код получателя / установщика:
myObject.setField(value); // try to set field f_ to value
Этот пост о эмуляции свойств в C ++ .Вызов свойства выглядит как вызов общедоступного элемента данных, но для задания или получения реального значения частного элемента-члена используется пользовательский код UDF.
Что бы мы хотели сделать, это разрешить простое использование интерфейса (общедоступные данные)как член, без синтаксиса вызова функции), в то время как базовый метод получения / установки может быть сложным (делать больше, чем только назначение / чтение данных) .
Следующий код (мой коллега написал) представляет простую реализацию свойства:
#include <iostream>
template<class C, class M>
inline C* get_parent_this(typename M C::*member_ptr, M*const member_this)
{
//interpret 0 as address of parent object C and find address of its member
char* base = reinterpret_cast<char*>(nullptr);
char* member = reinterpret_cast<char*>( &(reinterpret_cast<typename C*>(base)->*member_ptr) );
//modify member_this with offset = (member - base)
return reinterpret_cast<typename C*>(reinterpret_cast<char*>(member_this) - (member - base) );
}
class Owner
{
int x,pr_y;
int get_y() {return pr_y;}
void set_y(int v) {pr_y = v;}
public:
struct
{
operator int() { return get_parent_this(&Owner::y, this)->get_y(); }
void operator =(int v) { get_parent_this(&Owner::y, this)->set_y(v); }
} y;
};
int main ()
{
Owner ow;
ow.y = 5;
std::cout << ow.y;
if( get_parent_this(&Owner::y, &ow.y) == &ow) std::cout << "OK\n";
if( (char *)&ow.y != (char *)&ow) std::cout << "OK\n";
return 0;
}
В приведенном выше примере есть простая пара получатель / установщик, которая не выполняет никакой дополнительной работы (например, проверка целостности или проверка границ), но этот код может быть сложным при выполнении проверки границ, проверки целостности и т. Д.Это только тестовый пример.
Не беспокойтесь о "странном" коде в шаблоне помощника get_parent_this
.Самая «ужасающая» вещь - это расчет смещения.Адрес nullptr (NULL, 0x0) используется в качестве заглушки.Мы не пишем и не читаем с этого адреса.Мы используем его только для вычисления смещения объекта владельца на основе адреса подобъекта .Мы можем использовать любой адрес вместо 0x0.Таким образом, это не имеет смысла.
Использование свойств:
- , если кто-то использует общедоступные свойства элемента данных, может быть полезно в случае: 1.1.отслеживать публичные вызовы членов данных, если что-то пойдет не так;1.2.обновить безболезненно устаревший код, основанный на использовании открытых элементов данных;
- Что вы думаете об эмуляции свойств в C ++?Это живая идея?Есть ли у этой идеи недостатки (покажите, пожалуйста)?
- Что вы думаете о расчете адреса объекта владельца по адресу объекта?Какие техники и возможные подводные камни вы знаете?
Пожалуйста, расскажите нам свои мысли!
Спасибо!