お世話になります。
ヘルプに
>>m_hFile は派生クラスによって意味が異なるので、使用することはお勧めできません。
m_hFile は、クラスを非ポリモーフィックに扱うときに都合がよいようにパブリック メ
ンバになっています。
となっているのですがm_hFileを使用せずCFileインスタンスがファイルを開いているか
判断するにはどうしたら良いのでしょうか?
むしろCFile::hFileNullの使用例でヘルプでも使用しているくらいなので困っています。
環境はVS2008 MFCです。よろしくお願いします。
文言そのままの意味なのではないかと思うのですけれど。
CFileクラスからの派生クラスが必ずしもファイルを直接扱うクラスとは
限らないので直接使った時に値が意味する状態は必ずしも一致しないと
言っているのではないかと思います。
なので、メンバー変数を直接使うのではなくて状態判定用のメンバー関数
等を使って対応しなさいという話ではないかと思います。
実際の話、判定用のメンバー関数があるのであればそちらを使って
判定するのが筋だと思いますし。
ちなみに派生クラスによって扱いが違うと言う話なので
その派生クラスでの扱いがわかっていて使うのはOKなのでは?
と言う気もします。
その辺は使用する派生クラスによって違うから画一的な意味で
使用しないようにしなさいと言う意味だと思います。
たとえば、「CMemFileの時は?」とかそういう問題ではないかと。
生のCFileクラスを使う分には気にしなくて良いと思います。
後はCStdioFileとかそういう派生クラスを使うときはどうなるかですね。
いっその事、IsOpenとか判定用の関数があれば話は簡単なのですけれどね。
訂正。
>なので、メンバー変数を直接使うのではなくて状態判定用のメンバー関数
軽く見てみる限りではIsOpenに相当する関数ってなさそうですね。
そういう関数がなくて、m_hFileをあてにするなと言う話になると
クラスを使う側で状態管理をちゃんとやれと言う話になりますかねぇ。
まあ、オープン済みフラグみたいな物を持って置いてOpenで成功したら
立てるみたいな事をすれば出来る話ですね。
CMemFileクラスの解説も見てみましたけれど、はっきりとm_hFileが
使えないとは書かれていないので微妙と言えば微妙ですね。
まあ、実質はファイルを扱うクラスでは無いので多分使えなそうと
言うのは想像できますけれど。
連投申し訳ない。
CFile::hFileNullの解説の話と
「m_hFile は派生クラスによって意味が異なる」は
矛盾しませんね、良く考えたら。
CFile::hFileNullの解説では
「CFile オブジェクトに有効なファイル ハンドルがあるかどうかを判断する」
とありますから、ファイルが開かれているかどうかとは書かれていません。
つまり「ハンドルが無効な状態」と「ファイルがオープンされている状態」は
等価ではないと言っているのではないかなぁ。
というか、ファイルが開かれている状態と言うのが存在しないクラスも
派生クラスの中には有りそうですし。
んと、CFile系の主な関数についてはC++の例外処理を付けることを
MSDNで薦めていますよね。
つまり、
何も例外が起きていなければうまく動作している。
と判断するしかないと思います。
ただ、CFile系の例外って結構多かったような.......
あとは、「m_hFile」デバッグモードで見ることまで認めていないわけでは
ないですよね。
リリースモードでおかしな動作をしたならば、デバッグモードでTrace()やDump()で
モニターしてみる手もありますね。
メンバに直接アクセスするのが気が引けると言う話でしょうか?
であれば、月並みですが、operator HANDLE() でごまかしちゃっては。
CFile File;
if(CFile::hFileNull == (HANDLE)File)
これなら気が引けない(笑)
お勧めできないと書かれている理由が「派生クラスによって挙動が異なること」で、
(→ポリモフィックに扱うための代替則を満たさない)
一方、非ポリモフィックに扱う際には便利だと書かれているわけですから、
CMemFile等とポリモフィックに切り替えて使う予定もなく、ファイル限定で
「ファイルを開いているか」を確認する(→非ポリモフィックな用法)なら、
「それを素直に使うのが都合がよく」、サンプルでもそうしているわけで、
それを避ける理由は逆にないと思います。
もしかして「CFileをポリモフィックに使う」ということが謎ですか?
それとも何か別の不安をお持ちですか?
回答ありがとうございます。
派生CStdioFileくらいしか使ってなく狭義&ローカルファイルのファイル操作です。
自分はデバイスが混在する場合クラスを使わずはHANDLEにWriteFileしてました。
なので今回ポリモフィックとは言いがたいですがVC6からVS2008へ移行する際にも
CFile::m_hFileではエラーが出るので(型問題ですが)
あまり信用してはいけないような気がしていました。
素直に扱う方向で処理します。
むぅ。個人的には
「m_hFile は派生クラスによって意味が異なるので、使用することはお勧めできませ
ん。」の部分は無視してかまわないと思います。根拠は
1.そもそもpublic宣言された変数に対して派生先が何をしようと、
それは派生先の責任なので、派生元がどうのこうの言うべきではない。
「変な値が入っていたら動かんよ」程度で十分。
2.HANDLEを引数とするコンストラクタが存在し、かつそれをm_hFileに代入
している。この場合CFile自身はこの場合デストラクタでの自動クローズ
処理を行っていない。つまり、m_hFileを管理していないことになる。
そもそも管理してもいない変数に対して「使用するな」はいかがなものか。
思うに、2.のコンストラクタを使う以外の、m_hFileへの直接代入は
変なことになるかもしれんのでやめてくれ、一方で、Attach()を用意できな
かった、秘密の事情があるのですよ・・・ということなのではないでしょうか。
うーん管理してないということは…
派生含めCFile::hFileNullはファイルを開けてないという意味で
共通使用できそうってことでしょうか?
>派生含めCFile::hFileNullはファイルを開けてないという意味で
>共通使用できそうってことでしょうか?
「CFileをprotectedに継承したクラス」が、それの内部で、
それを保障するならば、の条件付きだとおもいます。
当然、外部からはm_hFileが参照できませんので、
BOOL Is_Open(){ return ( BOOL)( CFile::hFileNull != m_hFile);}
とか、書いてあるのでしょう。
仲澤@失業者さんの話もわかるんですが、
使えないものを使っても不幸になるだけなので
使用法には注意と言う事で良いのではと思います。
まあ、publicのメンバー変数と言う時点で弄れちゃいますからねぇ。
本来はprivateにしておいてオープン中なのかチェックする関数とか
ハンドルが有効値かどうかチェックする関数を設けておけばよかった
のでしょうけれど。
結局、派生クラスがファイルを扱っていないクラスだとしたら
多分ハンドルはあてにならないだろうという部分はそのままだと思います。
CFileに関しては使えるでしょう。
CStdioFileに関しては確かめてみると言う手もあるかと。
実際の話、私はこれで判断指定無いのでなんとも。
結局の所、仲澤@失業者さんも共通で使えますとは書かれていませんし。
使えるかどうかはケース・バイ・ケースなので使う側で判断するしか
ないかと思います。