クラスのメンバ変数を参照時に更新させたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
natuno

クラスのメンバ変数を参照時に更新させたい

#1

投稿記事 by natuno » 11年前

コード:

class Tim {
public:
  int hour;
};
とあったときに,

コード:

int main() {
  Tim tim;
  cout << tim.hour << endl;
  return 0;
}
とすると,現在時刻を指すhour変数が
いつ参照しても,その時刻が表示されるように,
参照されるその直前に勝手に更新されるようにしたいです.
GetHour() { (hourを更新;) return h;}
という訳ではなく,参照する寸前で勝手に行いたいです.
ググるためのキーワードだけでも良いので,よろしくお願いします.

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: クラスのメンバ変数を参照時に更新させたい

#2

投稿記事 by softya(ソフト屋) » 11年前

なぜ、メンバ関数にしてはダメなのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かずま

Re: クラスのメンバ変数を参照時に更新させたい

#3

投稿記事 by かずま » 11年前

hour でなくて second を返していますが、メンバ変数へのアクセスです。
Enterキーを何度も押してみてください。

コード:

#include <iostream>
#include <string>
#include <ctime>

using namespace std;

class Tim {
    struct Hour { operator int() { return time(0) & 0xffff; } };
public:
    Hour hour;
};

int main()
{
    Tim tim;
    string s;
    while (getline(cin, s))
        cout << tim.hour << endl;
    return 0;
}

かずま

Re: クラスのメンバ変数を参照時に更新させたい

#4

投稿記事 by かずま » 11年前

こっちのほうがよかったかな。

コード:

#include <iostream>
#include <string>

using namespace std;

class Tim {
    class Int {
        int x;
    public:
        Int() : x(0) {}
        operator int() { return ++x; }
        Int& operator=(int k) { x = k; return *this; }
    };
public:
    Int hour;
};

int main()
{
    Tim tim;
    tim.hour = 100;
    string s;
    while (getline(cin, s))
        cout << tim.hour << endl;
    return 0;
}

かずま

Re: クラスのメンバ変数を参照時に更新させたい

#5

投稿記事 by かずま » 11年前

class Int の実体は int であって、ポンタを含まないから
代入演算子は不要でした。
int を引数とするコンストラクタがあればよいということで。

コード:

#include <iostream>
using namespace std;

class Int {
    int m;
public:
    Int(int n = 0) : m(n) {}
    operator int() { return ++m; }
};

int main()
{
    Int a = 3, b = 5;
    cout << a + b << endl;
}
参照されると更新するので、実行結果は 10 です。

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: クラスのメンバ変数を参照時に更新させたい

#6

投稿記事 by YuO » 11年前

C#などではプロパティと呼ばれる機能に相当しますね。
VC++限定なら,declspec(property)を使って擬似的に行うことができます。

で,調べてみるとC++ Properties -- a Library Solutionという,2004年4月9日に出されている,C++でプロパティをライブラリとして実現する為のpaperが見つかります。
現状でどういう扱いになっているのかはわかりませんが。
# N1384, N1600あたりと共に扱われているようですが…… http://www.open-std.org/jtc1/sc22/wg21/ ... n2869.html

natuno

Re: クラスのメンバ変数を参照時に更新させたい

#7

投稿記事 by natuno » 11年前

かずまさん,ありがとうございました.
大変助かりました.
おかげで現在時刻取得のちょっと凝った
クラスを作ることができました.

コード:

#pragma once

#include <time.h>

/* void main() {
	 Clock c;
	 cout << c.year;   // return this year;
	 cout << c.second; // return now second [s];
   }
*/

class Clock {
public:
	class C_Order {
	public:
		static SYSTEMTIME st;

		static Clock *c;
		static int s_order;
		int order;
		// int val;

		enum S_ORDER {
			YE, MO, WE, DA, HO, MI, SE, MS
		};

		C_Order() {
			order = ++s_order;
		}
		operator int() {
			GetLocalTime(&st);

			switch(order) {
				case YE : return st.wYear;
				case MO : return st.wMonth;
				case WE : return st.wDayOfWeek;
				case DA : return st.wDay;
				case HO : return st.wHour;
				case MI : return st.wMinute;
				case SE : return st.wSecond;
				case MS : return st.wMilliseconds;

				default : return -1;
			}
		}
	}year, month, week, day, hour, minute, second, mseconds;

};

SYSTEMTIME Clock::C_Order::st;
int Clock::C_Order::s_order = Clock::C_Order::YE-1;

/*
#include <Windows.h>
#include <string>
#include <iostream>
using namespace std;

int main() {
	Clock c;
	
	cout << c.year << endl;
	cout << c.month << endl;
	cout << c.day << endl;
	cout << c.week << endl;
	cout << c.hour << endl;
	cout << c.minute << endl;
	cout << c.second << endl;
	cout << c.mseconds << endl << endl;
	
	Sleep(2100);
	cout << c.second << endl;
	cout << c.mseconds << endl << endl;
	Sleep(2100);
	cout << c.second << endl;
	cout << c.mseconds << endl;

	return 0;
}
*/

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: クラスのメンバ変数を参照時に更新させたい

#8

投稿記事 by h2so5 » 11年前

そのようなプロパティのエミュレートでは、こういうコードを書いた時に意図した結果にならないのでオススメしません。

コード:

int main() {
    Clock c;
    auto sec = c.second;
    
    Sleep(2100);
    cout << (c.second - sec) << endl;

    return 0;
}

アバター
せんちゃ
記事: 50
登録日時: 14年前
住所: 江別市東野幌町
連絡を取る:

Re: クラスのメンバ変数を参照時に更新させたい

#9

投稿記事 by せんちゃ » 11年前

Clockが一回しか使われないという保証はどこにもないので
複数生成されたとき、s_orderがenum S_ORDERの範囲を超えて期待しない値が戻るようになります。
C_Orderのメンバ変数は全てpublicになっていますが外部からst、c、s_order、orderを全て呼ぶことができてしまいます。
これらのデータは全て隠すべきです。
ヽ(*゚д゚)ノ カイバー

natuno

Re: クラスのメンバ変数を参照時に更新させたい

#10

投稿記事 by natuno » 11年前

YuOさん,
__declspec(property(get = Get_v, put = Put_v)) int u;
はいろいろ出来そうで楽しそうです.

コード:

class Clock {
public:
	int Getter() {
		return 1234; // hour, minuteなどの時間を返したい.
	}
	__declspec(property(get = Getter))
		int year, month, week, day, hour, minute, second, msecond;
};
求めていたのはまさにゲッターとセッターの関数が定義出来る
これなのですが,hour, minute, などのゲッター関数をたくさん定義し,
一つ一つ紐付しないといけなさそうなので,今回は見送ります.

C++ Properties -- a Library Solutionの文献のほうなのですが,
汎用クラスが定義してあって使いやすそうです.
唯一,英語力に乏しいこともあり,IndexedPropertyクラスが
良く理解できませんでした.
thing.Assignments[ "Coffee" ] = "Francis";
などから,Rubyで言うハッシュのことだとは思いました.

ありがとうございました.

natuno

Re: クラスのメンバ変数を参照時に更新させたい

#11

投稿記事 by natuno » 11年前

まさかコメントが返ってくるとは思ってませんでした^^
ので,改良しました.
WORD *Clock::pst = (WORD*)&Clock::st;
あたりは批判が来そうです.
あと,autoについては対策が思いつきません.
どうすればいいのでしょうかね.

コード:

#include <time.h>

/* void main() {
	 Clock c;
	 cout << c.year;   // return this year, update always when refering
	 cout << c.second; // return now second [s];
   }
*/

class Clock {
private:
	static SYSTEMTIME st;
	static WORD *pst;

public:
	class C_Order {
	private:
		static int s_order;
		int order;
		
		enum S_ORDER {
			YE = 0, MO, WE, DA, HO, MI, SE, MS, SO_MAXSIZE
		};
		
	public:
		C_Order() {
			order = ++s_order;

			if(s_order == MS) {
				s_order  = -1 ;				//リセット
			}
		}
	
		operator int() {
			GetLocalTime(&st);
	
			return 
				0 <= order && order < SO_MAXSIZE ?
					pst[order] :			// 正常
					-1;						// 異常

			/*
			switch(order) {
				case YE : return st.wYear;
				case MO : return st.wMonth;
				case WE : return st.wDayOfWeek;
				case DA : return st.wDay;
				case HO : return st.wHour;
				case MI : return st.wMinute;
				case SE : return st.wSecond;
				case MS : return st.wMilliseconds;

				default : return -1;
			}
			*/
		}
	}year, month, week, day, hour, minute, second, mseconds;
	
};

SYSTEMTIME Clock::st;
WORD *Clock::pst = (WORD*)&Clock::st;
int Clock::C_Order::s_order = Clock::C_Order::YE-1;

/*
int main() {
	//Timer tim;
	//cout << tim.GetHour();

	Clock c;
	
	cout << c.year << endl;
	cout << c.month << endl;
	cout << c.day << endl;
	cout << c.week << endl;
	cout << c.hour << endl;
	cout << c.minute << endl;
	cout << c.second << endl;
	cout << c.mseconds << endl << endl;
	
	Sleep(2100);
	cout << c.second << endl;
	cout << c.mseconds << endl << endl;
	Sleep(2100);
	cout << c.second << endl;
	cout << c.mseconds << endl;

	return 0;
}
*/

閉鎖

“C言語何でも質問掲示板” へ戻る