Вероятно, лучшим вариантом в настоящее время является использование атрибута __declspec( property( get=get_func_name, put=put_func_name ) ) PropertyType PropertyName
в Microsoft.
- также поддерживается clang,
- он преобразуется в ваш метод получения / установки при компиляции (не добавляет никаких новых переменных),
- используется, это самая близкая вещь к реальному свойству (может получить доступ к свойству свойства ...).
Но если вы используете другие компиляторы, вы можете использовать макросы:
#define PROPERTY_GEN(Class, Type, Name, GetMethod, SetMethod) \
class Property_##Name { \
public: \
Property_##Name(Class* parent) : _parent(parent) { } \
Type operator = (Type value) \
{ \
_parent->SetMethod(value); \
return _parent->GetMethod(); \
} \
operator Type() const \
{ \
return static_cast<const Class*>(_parent)->GetMethod(); \
} \
Property_##Name& operator =(const Property_##Name& other) \
{ \
operator=(other._parent->GetMethod()); return *this; \
}; \
Property_##Name(const Property_##Name& other) = delete; \
private: \
Class* _parent; \
} Name { this };
// PROPERTY - Declares a property with the default getter/setter method names.
#define PROPERTY(Class, Type, Name) \
PROPERTY_GEN(Class, Type, Name, get_##Name, set_##Name)
Затем используйте их как:
class SomeClass
{
public:
PROPERTY(SomeClass, int, Value)
int get_Value() const { return _value; }
void set_Value(int value) { _value = value; }
private:
int _value = 0;
};
int main()
{
SomeClass s, c;
s.Value = 5;
c.Value = 3 * s.Value;
s.Value = c.Value;
}
Вы также можете добавить другие варианты макросов для свойств только для чтения, только для записи и неконстантных методов получения только для чтения.Чтобы получить доступ к под-свойствам через ->, вы можете добавить оператор-> перегрузки в макрос.
По сравнению с __declspec (свойство (...)) в Microsoft методы getter и setter можно сделать закрытымино это не является реальным преимуществом, поскольку клиенту иногда может потребоваться получить адрес получателя / установщика.Недостатком является также наличие дополнительной переменной _parent для каждого свойства, и вам необходимо явно определить конструкторы копирования для родительских классов, если они используются.