鏑矢の憂鬱2000年1月後半
透明1ドットイメージ
 
2000/01/16 (Sun)
・今日はお休みだよーん。
透明1ドットイメージ
 
2000/01/17 (Mon)
・さいっきん、ぜんっぜんプログラミングしてないです(爆)。ただテストアプリ作ったりとかここの回答用のとかは結構作ってるんだけどね。アプリ作る総合力着けないとちょっとやばいかも? まーいーや。今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは、K-taです。
 
 いままで、いろいろと教えてくださってありがとうございます。
 ホイールが無効化できない原因がわかりました。
 インテリマウスでは正しくできるのですが、ロジテックのマウスで、[MS Compatible]にして、やろうとするとWM_MOUSEWHEELはフックできるものの、WM_NULLに修正しても、ホイールメッセージが送られてしまうようです。
 なぜ、ロジテックだとそうなるのかは、ちょっとわかりませんが(^^;ゞ
 ほかのメッセージは正しく修正できるようです。
 
#ちなみに、[MS Compatible]にしないとWM_MOUSEWHEEL自体が送られません
 
 お騒がせしましたm(_ _)m
透明1ドットイメージ
透明1ドットイメージ
 
・あらまー、ドライバの問題でしたか。たぶんなんかズルくさい方法でメッセージ送ってるんでしょう(爆)。ちなみに、 WM_MOUSEWHEEL が送られてない場合にはたいがい WM_VSCROLL が送られています。あ、もし WM_MOUSEWHEEL が間接的に WM_VSCROLL を送ってるんならこれにフック掛けるだけでうまくいくかも。あと MSWHEEL_ROLLMSG とゆー謎のメッセージの話も聞きかじりました。よーするに、結構面倒そうです……。
 
・もひとつツッコミ。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは尺八郎です
 
 まずはbezier曲線ですが、プログラムはあっています。
 
 表示上の目安としてはたとえば100*100ドットの範囲内で描画するとしましたら
fDt = 0.01
位です。ただ、それですと線が増えた場合に処理が遅くなるかもしれませんので適当に工夫が必要です。ただ、基本的に計算部分よりもLine関数の方が遙かに時間をとると考えてください。
 それと、Windows限定でしたらPolyBezierという関数がありますのでそれを使うのが一番手っ取り早いです。
 
 Singletonについて
 Singletonは基本的には継承しないものだというのは同意できます。
 それをふまえて「Singletonを継承」というのは
1、ベースクラスは何らかの抽象的なクラスで派生クラスはそれぞれ一つずつしかインスタンスが作成できない。
2、派生クラス含めてファミリー全体で一つのインスタンスしか作成できない。
 という2タイプが存在すると思います。
で、1は話に登った方法でできると思います。2の方はそうですね。実行時にトラップするのでしたら、ベースクラスのデストラクタを仮想にして何か細工を加えるというのはどうでしょう。
class base {
public
	base(){AddInstanse();};
	virtual ~base(){
		if (instanceNum == 1)
			instanceNum--;
		else
			SomeThingOddIsHappning();
		};

	void AddInstance(){
		if (instanceNum == 0)
			instanceNum++;
		else
			SomeThingOddIsHappning();
		};

private
	static int instanceNum = 0; // <- 便宜上ね	
};
	
 こうしておけば、基本的ですが多少のことには耐えられると思います。つまり、コンストラクタとデストラクタの両方を回避するようなコードを描かない限りはです。でも、破ろうと思えば簡単に破れますね。C++にもfinal指令があったら楽なんですけれどもね。
 
 ただ、2がどういう状況で必要になるのかはこれといって思いつかないんですよね、1のケースは結構あると思いますが・・・。
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。やっぱグラフィック関係は任せちゃった方がいいかも(爆)。 PolyBezier() なんて API があるんですねぇ。ってゆーか「ベジエ」のスペルが「Bezier」ってのが初耳……。 Singleton は参照カウント方式ですね。これだと「複数個」の時も拡張しやすいかもしんない。
 
・C++ の final 、欲しいなー。「自分と外から呼べるけど継承先から呼べない」みたいなアクセス指定子があったら良かったのに<それはそれで変っぽい気も。2のケース……タンスのうちひとつの引き出しだけしか開かないとか(謎)。
 
・おまーけー。わての場合 Singleton よりも、生成専用関数と private コンストラクタと friend 指定を使って処理することが多いです。こんな感じ。
 


class CTest;

CTest *Singletor();

class CTest
{
private:	//これがミソ。
	CTest()
	{}
	friend CTest *Singletor();
};

//	これでただひとつのインスタンスを返します。
CTest *Singletor()
{
	static CTest s_Instance;
	return &s_Instance;
}

	
 
・この方法のミソは「コンストラクタを private にする」ことっす。こうすることで普通に変数を作ることも継承することもできなくなります。で、 friend 指定したただひとつの関数でしかインスタンスを作れないとゆー。ホントは Singletor() は関数テンプレートにするんだけどねん。ってゆーかそのためにわざわざ static メンバ関数にしなかったってゆーか。このクラスだけでいいんなら static メンバ関数で、ってそれじゃ Singleton と同じですねー。なんかわけ分かんなくなってきた。
 
・余談だが gcc はコンストラクタを private にすると文句たれる(爆)。ちゃんと使い道あるんだから警告なんて出さないでー。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/18 (Tue)
・今日は書くことないんでつらつらと。昨日「えぴすてーめーのオブジェクト指向的日常」を購入しました。んで初めて「 Observer と Observable 」とゆーもんを知りました(汗)。VC付属のMSDNにはVJのドキュメントも入ってるんで、簡単に調べられるのがいい感じです。
 
・JAVAのライブラリは「インターフェイスのこだわり」みたいなものがあって、結構参考になるかなー。C++のは実装用ってのが多くてね。Cで書いたものをクラス化やラッピングしただけって感じのは(使うのは便利かもしんないけど)つまんないです(爆)。
 
・んでもC++使ってると、ただ単にクラスだけの関係に終止させるのってつまんなく感じちゃったり(爆)。テンプレート化したりしたくなっちゃうのは立派な病気なんだろうなぁ。皆さんはこうならないように、ととりあえず言っとこう。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/19 (Wed)
・今日もプログラミングしてなかったり(汗)。ま、今日はしゃーないんだけど。
 
・ここ最近、プログラミング辞書が盛況でうれしいです。今日は「オブジェクト指向」とか。実は辞書の「オブジェクト指向プログラミング」の欄はわて的にも満足のいくもんじゃないんだけど、この辞書は、満足のいかない部分を手直しし始めるとキリがないんで(爆)。だからこーやって送られてきたときをいい機会に直すわけですねー。
 
・「オブジェクト指向プログラミング」、わてはまともなプログラミングをVCから始めたってこともあってかなり長いつきあいをしています。んでも、やっとこさ、ここ最近わかり始めたかも。今回の辞書にも書くけど、かなゆ〜で今度しっかり解説しようとも思ってます。
 
・余談。「猫之妙術」とゆー本にこんなことが書かれてました。「知る者は言わず。言う者は知らず」と。つまり、本当の知識とは人に教えられるものではないということ。うーむ……。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/20 (Thu)
・今日も辞書書いただけ。土曜日が潰れちゃうんで、明日ぷらとわ書かないとちょっとやばいな。むぅ。とゆーわけで今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 Valiosです。
 Singletonの実装方法ではとっても勉強になりました。どうもありがとうございました。(テンプレートを使う手も確かにありますね)
 自分が思っていたのは継承ファミリーの中で1つの実体を生成した後は他の継承ファミリーを生成しない(例えばNULLを返すとか例外をthrowするとか)で、生成したクラスを要求した時は、その実体のポインタを返すとか出来ればいいなぁ…って思いました。
 具体的には、「Direct Music」のラッパクラスを作った後にそのクラスを拡張して機能を増やした「Direct Music拡張クラス(例:イベントに同期させるとかできるようにする)」を作成したする時に使えると思います。COMを用いた場合は2つ以上のインスタンスが出来るとまずいのでどうしてもSingletonにしたかったという訳です。
 この場合はインターフェイスの継承ではなく、あくまで機能の拡張っていう事になりますよね。(多分)でも、あの例とかを見ると、とっても複雑になりそうな予感が…。
 やっぱりSingletonの継承は行わない方が賢明っぽい気がします。(笑)
 というか、なんか設計が間違っているような気もします。こういう場合は、どういう設計にするとbetterなんでしょうか。
 
[ここからが今回の質問です]
 CallBack関数というのがある事は知っていますが、自分では作った事がありません。これを使うとどんな事が実現できるのか、また、どのように定義すれば良いのか教えてください。
 お願いします。
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。COMインターフェイスですかー、これは結構やっかいかも。動的に取得しなきゃいけないし、呼び出しの順序とか考えなきゃいけなそうだし。 Direct Music 自体は使ったことないんでよく分かんないけど、「生成用関数(たとえば DirectDrawCreate() にあたるものとか、 CoCreateInstance() とか)」のラッパー関数を作って、そこで1個だけ返すようにすると管理しやすいかなーとか思うです。んでも QueryInterface() とか使う必要がある時は結構大変かも……。
 
・「コールバック」っていうのは、日本語に訳すと「折り返し電話してね」って意味です(爆)。「金菜さんが帰りましたら、 xx-xxxx-xxxxx まで折り返し電話するようお伝え願えませんか」という感じ。話者が「アプリケーション」、相手が「ウィンドウズ」、電話番号が「コールバック関数のアドレス」になります。すると、あとで電話が掛かってくる、つまりコールバック関数が呼ばれるわけですねー。
 
・具体的には……結構コールバック関数を使うものって多いんだよねー、どれにするかな……。そうやね、今回は EnumWindows() を使ってみましょう。なぜかってゆーと、わてがまだ使ったことないから(爆)。この関数は、を呼び出すと、子じゃないウィンドウ(つまり親ウィンドウ)のハンドルが次々とコールバック関数へと送られてきます。こんな感じ。
 


//	コールバック関数。
//	この関数が親ウィンドウの数だけウィンドウズから呼ばれます。
BOOL CALLBACK EnumWindowsProc( HWND p_hWnd, LPARAM p_lParam )
{
	char ch[260];
	::GetWindowText( p_hWnd, ch, 256 );
	TRACE( "%s\n", ch );
	return TRUE;
}

//	コールバック関数をセットします。
void SetCallbackFunction()
{
	::EnumWindows( EnumWindowsProc, 0 );
	TRACE0( "終わったよん\n" );
}

	
 
・まずコールバック関数の EnumWindowsProc() から。コールバック関数は、必ず指定の引数・戻り値を持った関数じゃなきゃいけません。メンバ関数じゃダメよ。C++規定でメンバ関数と普通の関数は型が違うからね。 static メンバ関数なら大丈夫。引数とかの「指定」については EnumWindowsProc() のドキュメントを見てね。
 
・ドキュメントにも書いてあるとおり、この EnumWindowsProc って関数名や、引数名は変えてもOK。型があってりゃいいってことね。 CALLBACK ってのは引数や戻り値の「渡し方」の指定方法。コールバック関数はウィンドウズ、つまりアプリの外から呼び出されるんで、引数の渡し方をちゃんと決めとかないとうまく呼び出せないわけ。「あ、うちのピッチはあんたの携帯じゃ呼び出せないから家から電話してくんない?」とかゆー感じ<そうか?
 
・んで EnumWindows() の第2引数にさっきのコールバック関数の小カッコなし(つまり関数のアドレス)を渡すと、親ウィンドウのウィンドウハンドルとともに次々とコールバック関数が呼ばれるわけです。全部のウィンドウが渡されるか EnumWindowsProc() で FALSE を返すと呼び出しが止まって、この時点で EnumWindows() から返ります。
 
・これがコールバック関数の基本。ウィンドウプロシージャもフックプロシージャも Enum 系も、コールバック関数はこんなふうになってます。ちなみにおまけ。とある方法を使うと、メンバ関数ポインタを普通の関数ポインタにキャストできちゃいます。あら危険。ま、引数の渡し方とかうまくいかないからその辺で落ちちゃうけどねん。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/21 (Fri)
・んじゃ、今日もお便り(だけ)いってみよー! まず1通目。
 
透明1ドットイメージ
透明1ドットイメージ
 どうも、キャリコです。
 
 突然ですが、鏑矢さん fj は読まれてます?
 今 fj.comp.oops が熱いです!
 
 ちょっと(かなり?)ついて行けない話もありますが、読んでて面白いです。
# 「UMLなんか有害」といった発言も出たりとか。(^_^;;;
 
 興味がわいたら見てみてください。
 
 それでは。
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。ってゆーかこっちにも勝手に掲載しちゃってゴメンです。とりあえず確認できたのは「型はあった方がいい? ない方がいい?」とゆースレッドだけでした。んでもこのスレッドだけなのになんかでかい(汗)。よくこんだけ議論できるのー。
 
・んで、型についてはわては当然あった方がいいとゆー結論。型があるからこそコンパイルタイムエラーが出てくるわけで、これがないとかなり不安。ポリモーフィズムよりもテンプレートを多用するのもこーゆー面があるかな。……それとも型がなくてもコンパイルエラーが出せる方法があるのかなぁ(汗)。
 
・思うんだけど、ポリモーフィズムってプログラマー側だけで考えていいのかなぁ。ラーメン屋にラーメン頼んで「どんなんが来てもいい」と思う人はそういないでしょう。やっぱ「今日は味噌」とか思うわけで、そこでしょうゆ出されたら死ねます(泣)。ランタイムで振るまいが大きく変わるんだったら、プログラム的な仕組みなしで、その振る舞いをアプリユーザーが自由に変えられた方がいいんじゃないかなと思う。プラグインみたいにね(あ、これはプログラム的な仕組みが必要か……)。
 
・前々から、プログラムってもっと簡単に作れないかなーとか思うです。「ソリッド」じゃないけど、それこそパーツを組み替えるだけでできるような、アプリユーザーが自由に組み替えられるような。オブジェクト指向プログラミングってのはそういう方向性から始まったものだしね。プログラマーのためのプログラミング言語じゃなく、万人のためのツール。もちっとスキルと時間とお金があったら、挑戦してみたいですねー。
 
・お便り、2通目。
 
透明1ドットイメージ
透明1ドットイメージ
 Valiosです。  ごめんなさーい、詳しく説明できなくて。自分がCallBack関数について聞きたかったのは、ユーザー側が関数のポインタを設定して呼び出すのではなくて、昨日の例で言えば::EnumWindowsはどうやって定義しているんだろ?っていう事です。
 またメッセージプロシージャやドライバの列挙関数などもCallBack関数を呼んで何回も繰り返すのですが、これはユーザー側は同じような処理はできるんですか? それともこれはOS(Windows)の機能なんでしょうか? 他の環境でも行えるんでしょうか?
 
[こんな風になってるんじゃないか?っていう予想のコード(謎)]
 
typedef bool (*Pfunc)();

void EnumHoge(Pfunc pf)
{
	for(int i=0;i<10;i++){
		TRACE("%d回目の呼び出しです\n",i);
		pf();
	}
}

bool CallHoge()
{
	TRACE0("CallBack関数様の呼び出しだぞ\n");
	return true;
}

void SetHoge()
{
	::EnumHoge(CallHoge);
	TRACE0("しゅうりょ〜\n");
}
	
 
 なんか全然違う気がする…(笑) コードも確認してないし動きそうにないような。だいたいこの例では何の使い道があるのかさっぱり(^^; やっぱりアプリを作成したりするプログラマには無縁の観念なのかな? 他の誰かが作成したEnum関数は利用をさせてもらっているんですけど。
 
 それからstaticメンバにすればメンバ関数も設定できるんですね。
 これは良い事を聞きました。
透明1ドットイメージ
透明1ドットイメージ
 
・なるほど、コールバック関数を受け取る側ですね。この予想コードはずばりちゃんと通ります。たぶんこんなふうに実装されてるんでしょう。DLLの境界も越えられるはず。他の環境でも使えるんじゃないかなー。ドキュメント持ってないんで明確には言えないけど、たぶん。
 
・あと、やっぱ関数ポインタはちょっと怖いってのもあるんで、C++であればポリモーフィズムを使って実装する方がいいんじゃないかなー。例はこんな感じ。
 

//	抽象クラス。
class CHogeInterface
{
public:
	virtual void CallbackFunction( int p_i ) = 0;
};

//	列挙関数。
void EnumHoge( CHogeInterface &p_rcHoge )
{
	for(int i=0;i<10;i++)
		p_rcHoge.CallbackFunction( i );
}

//	実装クラス。
class CHoge
	:public CHogeInterface
{
public:
	virtual void CallbackFunction( int p_i )
	{
		TRACE( "CHoge::CallbackFunction() : %d\n", p_i );
	}
};

//	お試し。
void SetHoge2()
{
	CHoge cHoge;
	EnumHoge( cHoge );
	TRACE0( "終了!\n" );
}
	
 
・抽象クラスと列挙関数はライブラリ側で用意されてて、実装クラスとお試し関数はライブラリユーザー側で作る、って感じ。よーするにCOMインターフェイスみたいな感じです、立場逆だけど(汗)。実際には、こーゆーことをするとライブラリユーザーに多重継承を強いたりせにゃならんので結構問題あるかな(このまえの Singleton のときみたいにね)。ま、こんな例もあるってことで。
 
・では3通目。
 
透明1ドットイメージ
透明1ドットイメージ
 はじめまして,えちぜんといいます。
 ウィンドウの分割を(CSplitterWnd)使って,同じドキュメントから複数のビューをつくる方法はよく本に載っているのですが,分割せずに新しい子ウィンドウを作るにはどうしたらいいのでしょうか?
 具体的には表示した画像に対しての計測結果を別ウィンドウに表示のようなことをやりたいです。
 プログラムはMDIで作ってます。
透明1ドットイメージ
透明1ドットイメージ
 
・どうもはじめましてー。MFCのドキュメントビューアーキテクチャーは複雑なんでねー、なかなか難しいですよね。ただ、ソースコードが付いてるってのが結構救いかもしんない。ま、それは置いといて…… CTestApp::InitInstance() の中にドキュメントテンプレートを登録してるとこがあるでしょ。そのあとにこのコードを追加してください。
 


	CMultiDocTemplate* pDocTemplate;
	pDocTemplate = new CMultiDocTemplate(
		IDR_T_JUNKTYPE,
		RUNTIME_CLASS(CTestDoc),
		RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム
		RUNTIME_CLASS(CTestView));
	AddDocTemplate(pDocTemplate);
	//	ここまでは既存のコード。こっから下を追加してください。

	pDocTemplate = new CMultiDocTemplate(
		IDR_T_JUNKTYPE1,
		RUNTIME_CLASS(CTestDoc),
		RUNTIME_CLASS(CChildFrame),
		RUNTIME_CLASS(CTest2View));	//ここだけ違うことに注意。
	AddDocTemplate(pDocTemplate);

	
 
・ドキュメントテンプレートってのは、ドキュメント・ウィンドウ・ビューの組み合わせの設定みたいなもんです。ここでは、もともとのビューの他に、計測結果を表示するビュー( CTest2View )も登録します。こうすることで、1種類のドキュメント、1種類の子ウィンドウ、2種類のビューを登録できます。
 
・このままだと「最初に登録したウィンドウ」しか表示されないはずです(……なんでだろう(汗))。というわけで、結果計測ウィンドウは別のとこで表示することにします。「計測結果ウィンドウを作成しようとする関数」の中に、こーんな感じのコードを書き込んでください。
 

	CWinApp *pcWinApp
		= AfxGetApp();
	//	超決め打ち!! 絶対こんなことせんように<ならするなって。
	//	1個目のドキュメントテンプレートとドキュメントを取得。
	POSITION pPos
		= pcWinApp->GetFirstDocTemplatePosition();
	CDocTemplate *pcTemplate
		= pcWinApp->GetNextDocTemplate( pPos );
	POSITION pDocPos
		= pcTemplate->GetFirstDocPosition();
	CDocument *pcDoc
		= pcTemplate->GetNextDoc( pDocPos );

	//	2個目のドキュメントテンプレートを取得。ドキュメントはないはず。
	pcTemplate = pcWinApp->GetNextDocTemplate( pPos );

	//	ここでウィンドウ作成。
	CFrameWnd *pcFrameWnd
		= pcTemplate->CreateNewFrame( pcDoc, NULL );
	//	んで初期化。
	pcTemplate->InitialUpdateFrame( pcFrameWnd, pcDoc );
	//	はい、子ウィンドウができてるはず。
	
 
・まず登録されているドキュメントテンプレートを検索します。ここでは「最初のと次の」と決め打ちしてるけど、実際にはちゃんとチェックしてください。で、1番目ののドキュメントテンプレートからドキュメントを取得して、それを取っておきます。2番目のドキュメントテンプレートは「結果表示ビュー」を登録してるののはず(ホントはちゃんとチェックするのよ)なんで、これとさっきのドキュメントを使って子ウィンドウを作成します。
 
・これで、ドキュメントひとつに2種のウィンドウを作成できるはず。こーゆー仕組みなんだってことが分かるまでが、MFCの難しいとこかもしんないですねー。でも分かっちゃうと、結構使いやすいかもしんない(汗)。さっきも言ったけど、ソースコード着いてるしね。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/22 (Sat)
・いきなりだけど今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 どうも、キャリコです。
 
 コールバック関数についてですが、これは狭義の Observer パターンだと思うのですがどうでしょう?
# 違うか!?
## あぁ 反論が怖い。(^_^;;;
 
 ちなみに 2000/01/18 (Tue) のかぶゆ〜に
> んで初めて「 Observer と Observable 」とゆーもんを知りました(汗)。
という話がありましたが、「オブジェクト指向における再利用のためのデザインパターン」の 313 ページにバッチリ載ってますよ〜。(^_^;;
透明1ドットイメージ
透明1ドットイメージ
 
・ぎく、ガンマパターンを憶えとらんことがばれてしもた(汗)。いやー、Cマガの連載も読み続ける根性なかったし……やっぱまずいですね(汗)。あ、注釈。「ガンマパターン」ゆーのは「オブジェクト指向における再利用のためのデザインパターン」に載ってる23のパターンのことね。 Erich Gamma さんが作った、デザインパターンのサンプルパターンで、これ憶えとくとクラス構造考えるのに便利です。だから勉強しないとね(泣)。春休みには勉強しよー。
 
・んで、昨日のはまんまオブザーバーっすね<今気付いた。 CHogeInterface が Observer で EnumHoge() が Observable にあたるっぽいです。あ、これはJAVAの場合。ガンマパターンだと Observable は Subject やね。……いやだからつまり、ガンマパターンなんか知らなくてもこーゆーのは作れるんですってば<ホンマかいな(汗)。
 
・でわまたっ!<あら早いね。
透明1ドットイメージ
 
2000/01/23 (Sun)
・今日はお休みでーす。ま、辞書の単語とかかなり追加してるんでそっちで楽しんでね<何をやねん。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/24 (Mon)
・ここ数日忙しくなると思うんで、基本的にお便り紹介が中心になりますんで<ってずっとそうだったって気がしなくもないが(汗)。では、今日のお便り。ホントは日記の方に送られてきたんだけど、こっちにも載っけることにしました。まずかったら言ってくださいです。
 
透明1ドットイメージ
透明1ドットイメージ
 先日は,ありがとうございました。
 
 子ウィンドウの作り方なんですが、1つ目のファイルに対しての処理はうまくいったんですが、2つめのファイルを開いた場合は、2つ目ではなく1つ目のドキュメントを処理していたので、現在アクティブになっているViewに対して処理を行うように、GetActiveDocumentを使って子ウィンドウを作りました。
透明1ドットイメージ
透明1ドットイメージ
 
・お、あらかたうまくいったみたいですね。そっかー、開いたファイル分だけドキュメントができるんだ。その辺の処理も必要だったか。やっぱ決め打ちはやばかったですね(汗)。 POSITION がイテレーターだったら操作楽だったんだけど、面倒だったんでサンプルコードでは決め打ちしちゃいました。でもテストならいいよねぇ(汗)。
 
・もうひとつお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 初めまして、CStringに付いて悩んでいます。  CStringを多用た場合、メモリのフラグメンティションが起こり、大きい容量のメモリを確保しようとしても確保出来なくなると思うのです。
 例えば、
 
CString str = "ABC";
CString str1="abcde";
	
 
 などを頻繁におこなった時、連続した大きいシステムメモリが、無くなり、連続した小さシステムメモリが、多くなる現象です。(メモリが、不連続になる)
 本当にこの様な現象が、起こるのでしょうか?
透明1ドットイメージ
透明1ドットイメージ
 
・フラグメントは起きるんじゃないかな。 CString は new を使ってフツーに文字列領域を確保しているんで、場合によっては「解放された領域が小さすぎて活用されない」可能性が十分あります。確保・解放を頻繁にするとちょっとまずいかもしんないですが、まずいとしても自分でそういうのの無駄をなくすプログラムを書くのはかなり大変です(汗)。ま、こーゆーのはどっかのライブラリに入ってそう。
 
・ま、とりあえずは「大きい領域が確保できない」ことはまずないと思います。ポインタが取りうる最大の値として「4Gバイト」まで領域確保できます。実際には予約領域とかがあるんで全部取れるわけじゃないと思うけど、少なくともちょっとやそっと CString を使ったくらいで困るようなサイズじゃないと思うです。ま、この辺は作るアプリ次第ってとこかも。エディタとかならちゃんと考えなきゃダメだろうしねー。
 
・うーむ、こーゆーもはやっぱ苦手だ(爆)。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/25 (Tue)
・今日もお便りだけだぁ!
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは尺八郎です
 
 Javaではobserver等のデザインパターンがUtilとしてインタフェースが定められていたり実装されていたりして便利みたいですね。
 ところでInpriseがJBuilderFoundationをただで配布していますよね。
 NT, Linux, Solaris版が同じ環境で出そろっています。私はNT版を試してみましたがなかなかよさげです。画面が完全にSwingなのでちょっとあれって感じもありますがよくできています。KABさんも試してみられてはいかがですかね。でも、なぜかWin98では動作しない・・・。いや、まあ、NT版ってそういうことか・・・。でも、Javaなのになぜ?
 
 それから、string
 規模にもよりますがふつうのプログラムではあまりフラグメンテーションは気にする必要はないと思います。OSのメモリ管理ルーチンはおおよそ小さいアロケーションはバッファが用意されていましてそこから溢れない限りはかなり効率よくやっています。また、大きいアロケーション(4k以上位から)はまた別の領域に確保されます。ですので、ふつうは可変値を扱うデータベースが1ヶ月動き続けるとか言うような重量級のタスクでない限りは大丈夫のはずです。で、Windowsはここら辺はかなりいい加減にできていますので自分のプログラムによって発生するフラグメンテーションよりもOSそのもののメモリリークなどで沈没します。
 どうしても気になる場合はガベージコレクタを使うのが一番の早道です。
 std::basic_string< char, gc_alloc >
 で、行くはずなんですがなんか、なんかうまくいきませんでした。
 まあ、どちらにしろ解決するには相当つらいコーディングをしなければならないのでやめておいた方がいいと思います。
 ちなみに、CStringは64K以上の文字列を扱うといろいろ問題が生じるようです。まあ、そうじゃなくても大きめの文字列は扱いづらいようです。sgi版STLのropeがおすすめです。
 色々、ごたくを並べましたが まあ、気にしないのが一番です。
 
 ほなな〜
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。がびん、 JBuilderFoundation は Win98 では動かないのですか(泣)。 NT の入ってる研究室に入ったら試してみましょう。そいや Win2K はメモリ管理とか大丈夫なんかねぇ。実際、こーゆーのっていろんなOS試してみんとあかんかも。 std::basic_string のテンプレート引数、2番目は traits っすよ。3番目にしたらうまくいかもしんないです(試してない(汗))。うわー短いがここまで!
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/26 (Wed)
・今日もー、お便りだっけー(「運命」のテーマに乗せて読みましょう)。ではひとつめ。
 
透明1ドットイメージ
透明1ドットイメージ
 どうも、キャリコです。
# Java の話になるとつい反応してしまう(笑)
 
 尺八郎さん>
> Javaではobserver等のデザインパターンがUtilとしてインタフェースが定められていたり実装されていたりして便利みたいですね。
 
 私の場合は、基本的に Observer/Observable は使用しません。それは変更通知を受け取るためのメソッド名が update では抽象的過ぎるからです。
 その代わりに EventListener/EventObject を使用して具体的なメソッド名をつけるようにしています。
# まぁ、個人の好みでしょうけどね。
 
> ところでInpriseがJBuilderFoundationをただで配布していますよね。
..snip...
> でも、なぜかWin98では動作しない・・・。いや、まあ、NT版ってそういうことか・・・。でも、Javaなのになぜ?
 
 私もちょっと疑問です。Java VM 自体は Windows 95/98/NT4.0 で共通のものなのに、、、
 
> それから、string
..snip...
> どうしても気になる場合はガベージコレクタを使うのが一番の早道です。
 
 C/C++ にもガベージコレクタがあるとは、、、知らなかった。(^_^;;)
 恐るべし C/C++!(笑)
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。「 update では抽象的過ぎる」というのは実はとても核心をついてると思います。C++の演算子オーバーロードが効果的に働くのは、演算子が組込型で使えて、引数の数などがほぼ固定されていて、操作と結果が直感的・意味的に一致しているから。だから「データをアップデートさせるのよ!」とゆー意味を乗せて、組込型を含めたあらゆる型に update っちゅーメンバ関数があれば……どうなるんだろう(爆)。話がまとまんないな。やめやめ。
 
・C++のガベージコレクタは、生成に特別な関数を使うんでウィンドウズオブジェクトやCOMオブジェクトとかには使えないのがね。そいや、 Java でもウィンドウズオブジェクトやCOMオブジェクトを扱う場合あるですよね。そーゆーのもガベージコレクタが働いてくれるのかな? それともやっぱ DeleteObject() とか IUnknown::Release() とか呼ばなきゃなんないのかな?
 
・あ、考えたらそーゆーのはグローバルなもんもあるんだから、プロセスがハンドル失ったら削除していいってもんでもないですな。難しいのぉ。では次のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 CString フラグメンティションに付いてのご回答、有難う御座いました。
 参考にいたします。
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。実際のところ、プログラミング技術ってTPOが結構重要なんで、参考程度に聞いてうまく消化するといい感じになると思います。んじゃ、これからもよろしくねー。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/27 (Thu)
・今日もお便りだけですぅ。んでは今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 どうも、キャリコです。
 
> 「 update では抽象的過ぎる」というのは実はとても核心をついてると思います。
 
 こういったクラス名/メソッド名のつけ方などについては Java House ML では議論されているのですが、Visual C++ の ML(1, 2) では議論された記憶がありません。(私が知らないだけ?)
 C++ についてそういったことを議論しているところはないのでしょうか?
 
> そいや、 Java でもウィンドウズオブジェクトやCOMオブジェクトを扱う場合あるですよね。そーゆーのもガベージコレクタが働いてくれるのかな?
 
 Visual J++ ならそういったウィンドウズオブジェクトやCOMオブジェクトを使えると思いますが、本物の Java(笑)では使用できないのでわからないです。(^_^;;
 ただし、JNI を使用すればプラットフォームにネイティブな処理を行うことができますので絶対に使用できないわけではありません。
 実際に Java からCOMを使用するためのライブラリを開発して公開している方もいらっしゃいます。
> プログラマー's研究所/研究日誌 - 1999/09/26 [Java,COM] Java−COMブリッジ:JCom
# 私自身は上記のライブラリを使用したことがないので内部的な処理の詳細はわかりません。
 
 Visual J++ で思い出したのですが、Microsoft が独自に開発していた言語 COOL はどうなったんでしょう? 鏑矢さん知ってます?
透明1ドットイメージ
透明1ドットイメージ
 
・知らん(爆)。 MS はウィンドウズをどうするかで混乱しきってるんでしょう、きっと。 Mac OS X 、いいよなぁ……。「ウィンドウズオブジェクトやCOMオブジェクト」はどんな JAVA でも直接扱えると思ってました(汗)。特にCOMについては、 DirectX で使えるんだと思ってたんですが、生でインターフェイスポインタを操作したりするわけじゃないみたいですね(確信なし(汗))。ちょっと謎かも。
 
・クラス・メソッド名についてC++で議論された記憶はわてもないです。関数名の命名規則とかはかなり昔から議論されてるけど、それは結局「分かりやすい名前」が焦点ってだけで、現在のポリモーフィズムとかテンプレートとかの「名前そのものが意味を持つ」時代とは違うからなー。「オーバーライドして他のクラスから呼ばれる関数」みたいなのの名前を着けるとなると、その名前の意味が「ただ使うだけ」のものとはかなり違ってくるしねぇ。
 
・実際、もちっと考えてくれてもいいかも……。 カスタム iostream を作る場合、 std::basic_streambuf ってクラスの継承クラスを作るんだけど、そのオーバーライド用に用意された関数の名前が分かりづらいのばっかで、かなり苦労しました(泣)。 std::basic_streambuf::imbue() とかかなり謎……。 MFC だと、「最初のポインタを得るメンバ関数」が CList::GetHeadPosition() と CMap::GetStartPosition() って感じに違うし、もちっとなー。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/28 (Fri)
・今日もお便りだけよーん。
 
透明1ドットイメージ
透明1ドットイメージ
 尺八郎です
 
 ちらっとプログラム辞書覗いてみました
real
 ええっと広義には実数のことですね。狭義にはpascalの扱う6バイト浮動小数点型です。4バイトfloat 8バイトdoubleが一般的になって廃れました。
もともとpascalにはfloatもdoubleもなかったんですよ。realだけ。私が初めてpascalに触った頃はもう廃れかかっていました。
 でも、ほかの意味もあるかも・・・。
 
>COM
 この手のものは基本的にラッパークラスを作りますね。で、ラッパーがコレクトされたら中身もラッパーのデストラクタ(finalize())によって処理されると・・・。
 javaがコレクトしてくれるのはメモリだけですのでファイル、サービス、スレッドetcは全て手動で処理しなければなりません。ですので、コレクタが作動する前に明示的にオブジェクトを解放したい場合はいろいろと面倒なことがあります。
 
>COOL
 新手のギャクとしか思えない・・・
 
 ではでは
透明1ドットイメージ
透明1ドットイメージ
 
・質問でぇす。こんまえ買った「えぴすてーめーのオブジェクト指向的日常」の中で「 Java はデストラクタがなくて」と嘆いてたんですが、実際にはデストラクタに変わるものがあるって事? その「コレクト」(=「ゴミ拾い」?)した時に自動的に呼び出されるメソッドがあったりすると……でもいつ呼び出されるか分かんないってのはなんかなぁ。
 
・ real については結構困っちゃったですよ。尺八郎さんのおっしゃるとーり Pascal にはあるんだけど、それじゃ C++ 中心の辞書には載っけらんないし、 std::complex::real() を指してるとも思えないし、でも real って単語自体はかなり一般的だから簡単に「却下!」しちゃっていいもんかなぁとか。まー、あの辞書は結構偏ってるからテキトーでもいいのかも(爆)。
 
・今おそらく一番ヒット数があるであろうページ、プログラミング辞書。このページって楽なよーな大変なよーな(汗)。最初の単語数はそんな多くないんだけど、わての方で追加し始めるとあれよあれよと膨大な量に(爆)。今、「ウィンドウ」って項目を追加するかどうか迷ってます。きっとこの関連でもっと項目追加しちゃうだろうなぁ、うーむ。ま、あと2日あるからなんとかなるかも。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/29 (Sat)
・今日もお便りだけー。
 
透明1ドットイメージ
透明1ドットイメージ
 どうも、キャリコです。
 
 尺八郎さん>
> javaがコレクトしてくれるのはメモリだけですのでファイル、サービス、スレッドetcは全て手動で処理しなければなりません。ですので、コレクタが作動する前に明示的にオブジェクトを解放したい場合はいろいろと面倒なことがあります。
 
 私がプログラミングしている限りでは特に「面倒」なことはありませんでしたけど。(^_^;;
 それに「解放」はガベージコレクタの仕事ですし。
 # ソケット/ストリームを「クローズ」するのはもちろんプログラマの仕事ですが。(^_^;;;
 
> javaがコレクトしてくれるのはメモリだけですので
 
 Java を知らない人に語弊があるといけないので、説明を付け足させていただきます。m(_ _)m
 
 Java は C++ と違い、クラスのインスタンスは new を使用してのみ生成することができます。(スタックに割り当てることはできません)
 # JIT コンパイルされた場合は不明。
 
 ですので、上記の「コレクトしてくれるのはメモリだけ」というのは、オブジェクト(インスタンス)そのものを(参照カウンタがゼロになった時点で)ガベージコレクタが自動的に解放してくれる、ということです。
 # 厳密に言うと参照カウンタがゼロなった時点でスグに解放されるわけではありませんが、それを説明すると長くなるので割愛します。
 
 ちなみに、スレッドが生きている(動作している)限りは、たとえ参照カウンタがゼロになってもそのオブジェクトが勝手にガベージコレクトされることはありません。
 
 鏑矢さん>
> こんまえ買った「えぴすてーめーのオブジェクト指向的日常」の中で「 Java はデストラクタがなくて」と嘆いてたんですが、実際にはデストラクタに変わるものがあるって事? その「コレクト」(=「ゴミ拾い」?)した時に自動的に呼び出されるメソッドがあったりすると……でもいつ呼び出されるか分かんないってのはなんかなぁ。
 
 int や long などのプリミティブ型以外のすべてのクラスは、ガベージコレクトの対象になった場合に呼び出される finalize というメソッドを持っていますが、呼び出されるタイミングは基本的に不明ですので C++ のデストラクタの代わりに使用することはできません。
 強制的にガベージコレクタを走らせて finalize を呼び出すこともできますが、そんなプログラミングは Java ではやるべきではないでしょう。
 
 それに、Java の例外処理には C++ の例外処理(try 〜 catch)にはない finally というものがありますから、デストラクタが必要になることはないと思うのですが、どうでしょう?
 # そもそも Java でプログラミングするときは C++ のデストラクタの存在は完全に忘れたほうが良い?
 
 長文失礼致しました。m(_ _)m
透明1ドットイメージ
透明1ドットイメージ
 
・忘れた方がいいっぽいかも。後処理は必要なときに外から呼び出す、ってパターンが Java では一般的ということですねー。つまり「インスタンスの寿命」と「実際のオブジェクト(ファイルストリームやウィンドウ)の寿命」は別々って感じかも。「インスタンスは実オブジェクトのラッパー」って考えればそっちの方がいいかもしんない。
 
・ スレッドの話は「実際のスレッドと Thread インスタンスの寿命の関係」のことですね。「寿命の長い方に短い方が従う」ってのは分かりやすいです。CWnd みたいに「インスタンスなくなるときにウィンドウも Delete() する」ってのは結構迷惑だったからなー(汗)。
 
・こうやって見てくと、 C++ と Java は想像以上に違うなーとか。全体的な「流れ」と言うか「空気」と言うか、そういうのが違う感じ。見かけにとらわれないで、別物として捉えた方が「向いてる」プログラムが組めそうかなー。 C++ と Java をチャンポンしちゃうと、なんかものすごくもったいないプログラムができちゃいそう。まーだからこそ「言語を考えないプログラム」が重要なんかなぁ。
 
・お便りもひとつ。
 
透明1ドットイメージ
透明1ドットイメージ
 尺八郎です
 finalize()は本当はデストラクタではないことになっているんですよね。まあ、細かい用語についてはわからないことが多いと言うことで・・・。んでもって、明示的に呼べ(オブジェクトを破棄)ないというのは、破棄を許可するとすでに破棄されたオブジェクトを指すポインタ(ハンドル)ができてしまう(可能性がある)からだそうです。そう言うわけで、一応ハンドルにNULLを代入してコレクタを起動したら何とかなるんですけどね。でも、これだとでかいオブジェクトを作ったり消したりするプログラムだとオーバーヘッドがでかいようなんですよ。まあ、うまくやる方法は色々研究されているみたいなんですが・・・。
 
> real
 さすがにC++とはあんまり関係ないですねぇ。std::complex::real()はおそらくないでしょうしね。あ、データベース関係でもrealって言うこともありますか・・・。
 
 んじゃ
 
 そうですね。C++をは全く関係ないですよね。
透明1ドットイメージ
透明1ドットイメージ
 
・なるほど、つまり C++ で、 delete で解放したあとそのポインタ使っちゃうとかと同じ次元ですね。解放はガベージコレクタに任せる、つまりあるインスタンスへのすべての参照が失われたときだけに削除させるってことか、そー考えるといいなぁ。まー C++ でも常に NULL 渡すって決めとけばいいんだけど、常にできるもんでもないし。いつの間にか削除されてたとかね。やっぱこの辺はネックだなー。
 
・おまけー。 std::char_traits と std::valarray は STL に含まれてないよん。あの本に std::string が載ってるのはおまけだし(爆)。 STL と iostream は基本的に別物。関連性があるのは iostream 専用イテレーター( std::istream_iterator とか)があるくらい。イテレーターを介することでクラス間の依存度を大幅に下げてるってことかも。だから好き(爆)。 STL と iostream のメルマガ、もちっとまってねーん。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/30 (Sun)
・今日もお便りだけー。
 
透明1ドットイメージ
透明1ドットイメージ
 どうも、キャリコです。
 
 尺八郎さん>
> まあ、細かい用語についてはわからないことが多いと言うことで・・・。
 
 とのことですので用語の間違いについてのツッコミは置いといて、、、(^_^;;
 
> でも、これだとでかいオブジェクトを作ったり消したりするプログラムだとオーバーヘッドがでかいようなんですよ。まあ、うまくやる方法は色々研究されているみたいなんですが・・・。
 
 スバリ HotSpot VM のことですね。
 
 ハッキリ言って C++ より速いコードにコンパイルされる(!)場合もありますので、メモリの消費量を気にしなければかなり使えます。
 # IBM も HotSpot と同様に実行時プロファイリングを行っている JIT を配布しています。
 
 詳しくは Java House ML の下記スレッドおよびトピックス/アーカイブ等を参考にしてください。
> [JavaHouse-Brewers:17339] HotSpotがネイティブコードより速い訳
> [JavaHouse-Brewers:25330] HOTSPOT の実行速度について
 
 ***
 
 ここにはインターネットエクスプローラ(以下 IE)を使用しているユーザの方が多いと思いますので、この場を借りて IE のセキュリティホールの告知を行いたいのですが、鏑矢さん宜しいでしょうか?
 # もし、相応しくない内容でしたら削除してください。m(_ _)m
 
 このたび Java House ML において Microsoft VM for Java のセキュリティホールについての危険性が発見されました。(すでに他のニュースサイトでご確認された方もいらっしゃると思います)
> [JavaHouse-Brewers:30376] Warning: Yet Another Security Hole of `Microsoft VM for Java' (日本語)
> [JavaHouse-Brewers:30411] Re: Warning: Yet Another Security Hole of `Microsoft VM for Java' (英語)
 
 警告の対象は Windows 95/98/NT4.0/2000RC2 の IE4, 5 および Macintosh の IE4.0 の使用者です。
 IE をご使用の方は上記の内容を確認されることを強くお勧め致します。
 
 # 告知に協力していただいた鏑矢さんに感謝します。m(_ _)m
透明1ドットイメージ
透明1ドットイメージ
 
・どうもですー。この「ファイルを見られる」って MS のお庭芸って気が(爆)。でも最近感じるんだけど、ねすけって使いにくいわ(爆)。テーブル解析が下手だからページ全体の表示遅いし、なぜかいっぱい開くと落ちるし。 IE4 が一番バランスいいかも。ちなみにわては常に Java アプレットは動かないようにしてますです。今の Java は BGM 専用であれがイヤ〜ンで(汗)。
 
・今日のNスペ見てても思うんだけど、なんてゆーか、もっと「中」のセキュリティを上げてもいいんじゃないかなぁと。 Win32 API を使うのにセキュリティを掛けたり、重要なファイルは見られないようにしたり。そもそも、インストールで簡単に情報を書き換えられたり、どんなアプリもがどんなこともできるってのがね。つまりアプリに対するセキュリティみたいな? まーこれもイタチごっこかなぁ。
 
・でわまたっ!
透明1ドットイメージ
 
2000/01/31 (Mon)
・なんかイヤな予感するなー。今のところ、わてのところにまぐまぐ経由のかぶヘッダーが来てません(汗)。しかも、すでに配送したっつーお知らせが。実は先週は午後4時くらいに到着したんだよね。どうも広告をくっつけるサーバーでえらい手こずってるみたいです。ただ、広告付けるのやめたくないんだよねー。お金の問題じゃないのよ、現在えらい微々たるもんだし(泣)。
 
・今日はぷらとわ書いてました。ここでぷらとわの予定について書いときます。えっと……あ、今日送ったのにミスが(汗)。来週のぷらとわはクラス間のアクセス方法についてです。レジストリはその次の回。んで、それから CString 、参照、オーバーライド、リリースビルドと見ていくつもり。実は No.050 でちょうど1周年。そんときに区切りになるようにしたいかなーとか。
 
・なーんか、ものすごくゆっくり進んでるけど、でもこれで良かったかも。余裕持って、書きたいこと全部書けるからねー。バージョン情報なんてそうそう書けるもんでもないし。で、4月からは心機一転、かなり細かいとこから見てくつもり。んでもやっぱ、 MFC を読み解くってゆー方向性は変わってないかな。
 
・わての持論は「いいプログラムを書くためにいいライブラリを読むべし」。プログラムを書く上でいいお手本がないとね。 MFC がいいとは口が裂けても言えないけど、でもかなり分かりやすくソースコードが書かれてる珍しいライブラリだと思うです。とゆーわけでこれからも期待してねー。
 
・でわまたっ!
 
 
(C)KAB-studio 2000 ALL RIGHTS RESERVED.