ターゲット
Getter, Setterを書くのはダサい。
C#のプロパティみたいに変数名をそのまま使いたい。
宣言したクラスだけが書き込めるpublicメンバ変数を作りたい。
という人向けの内容です。
クラス
accesser.hpp
#pragma once
template <class Friend, class T>
class Accessor
{
friend Friend; // フレンドクラス
T m_var; // Tの実体
public:
Accessor() noexcept = default;
Accessor(T var) { m_var = var; }
~Accessor() noexcept = default;
public:
// 読み取りのための演算子をオーバーロードして公開
// 型変換演算子
operator T() const noexcept { return m_var; }
// アロー演算子
T* operator ->() const noexcept { return &m_var; }
// 間接参照演算子
T& operator *() const noexcept { return m_var; }
private:
// 書き込みのための演算子をオーバーロードして制限
// 単純代入演算子
T& operator =(const T& var) & { return m_var = var; }
T& operator =(T&& var) & noexcept { return m_var = var; }
// 複合代入演算子
T& operator += (const T& var) { return m_var += var; }
T& operator -= (const T& var) { return m_var -= var; }
T& operator *= (const T& var) { return m_var *= var; }
T& operator /= (const T& var) { return m_var /= var; }
T& operator %= (const T& var) { return m_var %= var; }
T& operator <<= (const T& var) { return m_var <<= var; }
T& operator >>= (const T& var) { return m_var >>= var; }
T& operator &= (const T& var) { return m_var &= var; }
T& operator |= (const T& var) { return m_var |= var; }
T& operator ^= (const T& var) { return m_var ^= var; }
// 後置インクリメント / デクリメント
T operator ++(int) { return m_var++; }
T operator --(int) { return m_var--; }
// 前置インクリメント / デクリメント
T& operator ++() { return ++m_var; }
T& operator --() { return --m_var; }
};
実用例
hoge.hpp
#pragma once
#include "accessor.hpp"
class Hoge
{
public:
// Accessor<フレンドクラス名, 変数の型名> メンバ変数名{初期値};
Accessor<Hoge, int> Number;
Accessor<Hoge, bool> Boolean{false};
Hoge() { Number = 100; } // フレンドクラス内からの書き込み可
~Hoge() {}
};
main.cpp
#include <cstdio>
#include "hoge.hpp"
int main(void)
{
Hoge hoge;
// hoge.Number = 0; // エラー、フレンドクラス外からの書き込み不可
printf("%d", hoge.Number); // フレンドクラス外からの読み込み可
getchar();
return 0;
}
改造案
- 書き込み制限系をすべて内部的なSetter経由にすることで、よりデバッグしやすくする