31
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++でProperty(getter/setter)

Last updated at Posted at 2013-11-04

C#のPropertyって便利だよね

C++でやるには?

とりあえず簡単に実装するなら名前を渡してメンバ変数とgetter/setterを定義するマクロ。
これは稀によく見る。
でもスマートじゃないよね。

じゃあもうTemplateしかないっしょ

書いてみた。
https://github.com/HogeTatu/cpp_module/tree/master/Property

Property基底

template <typename T>
class Property
{
public:
	Property(T& value) : _value(value) {}
	Property(const Property& ref) : _value(ref._value) {}
	virtual ~Property() {}

	Property<T>& operator = (const Property<T>& ref)
	{
		this->_value = T(ref._value);
		return *this;
	}

protected:
	T&		_value;
};

getter/setter有りなProperty

template <typename T, class Getter = SimplePropertyGetter<T>, class Setter = SimplePropertySetter<T>>
class WritableProperty : public Property<T>, private Getter, private Setter
{
public:
	WritableProperty(T& value) : Property<T>(value) {}
	WritableProperty(const WritableProperty& ref) : Property<T>(ref) {}
	virtual ~WritableProperty() {}

public:
	operator const T& () const { return this->Get(this->_value); }
	const T& operator -> () const { return this->Get(this->_value); }

	WritableProperty<T, Getter, Setter>& operator = (const T& var) { this->Set(this->_value, var); return *this; }
};

getterのみのProperty

template <typename T, class Getter = SimplePropertyGetter<T>>
class ReadOnlyProperty : public Property<T>, private Getter
{
public:
	ReadOnlyProperty(T& value) : Property<T>(value) {}
	ReadOnlyProperty(const ReadOnlyProperty& ref) : Property<T>(ref) {}
	virtual ~ReadOnlyProperty() {}

public:
	operator const T& () const { return this->Get(this->_value); }
	const T& operator -> () const { return this->Get(this->_value); }
};

デフォルトのgetterポリシー

template <typename T>
struct SimplePropertyGetter
{
	static const T& Get(const T& value) { return value; }
};

デフォルトのsetterポリシー

template <typename T>
struct SimplePropertySetter
{
	static void Set(T& value, const T& var) { value = T(var); }
};

実装内容

メンバ変数の実体をコンストラクタで渡して処理を委託する。
getter/setterの振る舞いはポリシーで切り替えられるようにした。

サンプル

こんなクラスがあったとして

class Sample
{
public:
	Sample()
		: _foo1(1)			, foo1(_foo1)
		, _bar1("bar1")		, bar1(_bar1)
		, _foo2(2)			, foo2(_foo2)
		, _bar2("bar2")		, bar2(_bar2)
	{}
	
	cpp_module::WritableProperty<int>			foo1;
	cpp_module::WritableProperty<std::string>	bar1;
	cpp_module::ReadOnlyProperty<int>			foo2;
	cpp_module::ReadOnlyProperty<std::string>	bar2;

private:
	int				_foo1;
	std::string		_bar1;
	int				_foo2;
	std::string		_bar2;
};

こんな感じに書ける。

Sample sample;

sample.foo1 = 10;
sample.bar1 = "sample.bar1";
output(sample.foo1);
output(sample.bar1);

//sample.foo2 = 20;					// コンパイルエラー
//sample.bar2 = "sample.bar2";		// コンパイルエラー
output(sample.foo2);
output(sample.bar2);

ちなみにポインタ型でプロパティを定義したら a->b の形でも参照できる。

Getter、Setterの振る舞いを変えたければ、自分でポリシーを定義して

cpp_module::WritableProperty<int, CustomGetter, CustomSetter>	foo1;

みたいにしたらいい。

ちょっと考えたけど思い付かなかったから匙を投げたもの

sample.bar1.c_str()

がエラーになる。

const std::string& bar1 = sample.bar1;
bar1.c_str();

だったらOK。
a.b のオーバーロードができないからなぁ。
「こんなやり方どう?」みたいなのあったら教えて下さい。
あと何かやらかしてたら指摘して頂けると勉強になります。

31
35
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?