Как скрыть поле через определение и предоставить только сеттер и геттер?
Интересно, как спрятать поле недвижимости (не делать его частным или общедоступным, а принудительно использовать сеттеры и геттеры) и предоставить ему простые сеттеры и геттеры. Поэтому мне интересно, как создать API, как:
private:
Property( int my_a);
public:
Property( int my_b);
...
{
set_my_a(1);
cout << get_my_a() << endl;
// my_a = 13; // will cause compiler error
...
Как создать такую вещь через препроцессор Boost?
2 ответа
Вам действительно нужно использовать форсированный препроцессор? у вас есть решение без повышения ниже:
// property.h
#include <stdio.h>
#define property(type) struct : public Property <type>
template <typename T>
class Property
{
protected:
T value;
public:
virtual T get() {
return value;
}
virtual void set(T new_value) {
value = new_value;
}
};
пример использования:
// test.cpp
#include "property.h"
class Test {
public:
property(int) {} a;
property(int) {
int get() {
return value * 10;
}
} b;
property(int) {
void set(int x) {
value = x * 200;
}
} c;
property(int) {
int get() {
return value * 3000;
}
void set(int x) {
value = x * 443;
}
} d;
};
main()
{
Test t;
printf("i\ta\tb\tc\td\t\n");
for (int i=0; i<10; i++) {
t.a.set(i);
t.b.set(i);
t.c.set(i);
t.d.set(i);
printf("%i\t%i\t%i\t%i\t%i\n", i, t.a.get(), t.b.get(), t.c.get(), t.d.get());
}
}
Решение википедии на http://en.wikipedia.org/wiki/Property_(programming) хорошо, но нуждается в минимальной модификации, чтобы стать полезным, потому что без защищенного оператора вы не можете написать свои собственные методы получения и установки,
#include <iostream>
template <typename T>
class property {
protected:
T value;
public:
T & operator = (const T &i) {
::std::cout << i << ::std::endl;
return value = i;
}
operator T const & () const {
return value;
}
};
struct Bar {
property <bool> alpha;
struct :public property <int> {
int & operator = (const int &i) {
::std::cout << "new setter " << i << ::std::endl;
return value = i;
}
} bravo;
};
main()
{
Bar b;
b.alpha = false;
b.bravo = (unsigned int) 1;
}
Вы можете изменить немного больше, если хотите:
#include <iostream>
#define SETTER(type) public: type& operator=(const type new_value)
#define GETTER(type) public: operator type const & () const
template <typename T>
class Property {
protected:
T value;
public:
T & operator = (const T &i) {
::std::cout << i << ::std::endl;
return value = i;
}
template <typename T2> T2 & operator = (const T2 &i) {
::std::cout << "T2: " << i << ::std::endl;
T2 &guard = value;
throw guard; // Never reached.
}
operator T const & () const {
return value;
}
};
struct Bar {
Property <bool> alpha;
struct:Property <int> {
SETTER(int) {
value = new_value * 1000;
::std::cout << "new method " << new_value << ::std::endl;
return value;
}
GETTER(int) {
return value/1000;
}
} bravo;
};
main()
{
Bar b;
b.alpha = false;
b.bravo = (unsigned int) 1;
::std::cout << b.bravo << ::std::endl;
}
Вместо того, чтобы переписать пример реализации, это ссылка на один из них в Википедии: http://en.wikipedia.org/wiki/Property_(programming)
Это в основном заставляет свойство быть доступным через методы получения / установки. Обновление, которое вам понадобится, чтобы получить желаемый эффект, - это возможность передавать функторы в эти свойства. Есть много идей по их реализации; лучший подход, который я не могу посоветовать, и зависит от ваших потребностей в развитии. Лично мне кажется, что это больше, чем просто проектирование, и я предпочитаю просто использовать Pimpl, чтобы скрыть мои личные данные и просто явно указывать методы получения / установки.