#pragma twice

KAB-studio > プログラミング > #pragma twice > 104 Version 6.04 あるのにない!!

#pragma twice 104 Version 6.04 あるのにない!!

前のページへ 表紙・目次へ 次のページへ

 Version 6.04
あるのにない!!

さて今回は、使えると思ったら使えない! って話
どゆこと?
たとえば、前に紹介したこんなコード

    int i;
    std::ifstream cIFStrm;
    cIFStrm.open( "Data.txt" );
    cIFStrm
        >> i;

ファイルから読み込むのだね
これは Ver 5.09 ( No.074 ) で紹介したね。たとえばこのコードが、本
に載ってるとかホームページに書いてあるとかで、そのまま書き写したとし
ます

void CDebugDlg::OnButton1() 
{
    int i;
    std::ifstream cIFStrm;
    cIFStrm.open( "Data.txt" );
    cIFStrm
        >> i;
}

これをこのままビルドするとエラーになります

DebugDlg.cpp
error C2653: 'std' : 識別子がクラス名でも名前空間名でもありません。
error C2065: 'ifstream' : 定義されていない識別子です。
error C2146: 構文エラー : ';' が、識別子 'cIFStrm' の前に必要です。

なんでだっけ?
えーっと、こういうのを使うためにはインクルードしなきゃいけないって
ことだよね。このときは確か fstream っていうのをインクルードしたね
そう、 std::ifstream の宣言が fstream ヘッダーファイルに書かれてる
から、これを使うためにインクルードする必要があるんです

#include "stdafx.h"
#include <fstream>       // ここ。
#include "FileTest.h"
#include "FileTestDlg.h"

こういうことは、 iostream だけじゃなくて、ランタイムでも API でも 
MFC でもあることだから
つまり、関数とかクラス使うためにインクルードしなきゃいけないことが
あるってこと?
そういうこと。基本的に MFC を使ってるときは、基本的な API 、ほとん
どの MFC 、一部のランタイムがそのまま使えるようヘッダーファイルをイ
ンクルードしてます
たとえば?
たとえば fopen() 。 MSDN で見てみて
 MSDN 〜
 MSDN の fopen() のリファレンスに〈必要なヘッダー〉ってあるでしょ
 stdio.h がそうだって書いてあるね。つまりこれが、インクルードしな
きゃいけないファイルなんだ。あ、でも
そう、 Ver 5.11 ( No.076 ) ではわざわざインクルードしてないでしょ。
これは、もともとインクルードしてるから
 MFC がってこと?
そういうこと。 MFC のインクルードファイル Afx.h でインクルードして
ます。ちなみに Afx.h は Afxwin.h でインクルードしてて、この Afxwin.h 
は各プロジェクトの stdafx.h でインクルードしてます
なんか複雑
うん、実際には〈インクルードされてるかどうか〉は調べなくていいよ。
来週解説するけど、調べるのも大変だし、2重にインクルードしても問題な
いから
ん? つまり、わざわざ stdio.h をインクルードしても大丈夫なんだ
そゆこと。で、どのヘッダーファイルにあるって知ってるならインクルー
ドしておいてもいいし、しないでおいてエラーが出たら、でもいいし
 std::ifstream が fstream にあるって調べるのはどうすればいい?
まずは MSDN 。ランタイムはさっき言った〈必要なヘッダー〉に書いてあ
るから。 MFC の場合は…… CWnd を見てみて
ほい。あ、下のとこに #include <afxwin.h> ってあるね
そう、これをインクルードすれば OK 
そういえばこれは stdafx.h でインクルードしてたんだ
 API の場合は…… GetWindowText() の API のを見てみて
日本語のと英語のがあるけど
両方とも。日本語の方は〈ヘッダ : winuser.h 内で宣言〉って書いてあ
るし、英語の方は "Header: Declared in winuser.h." って書いてあるし
これ見てインクルードすればいいんだね
それか【ファイルから検索】でどこにあるか調べるか。ただ、 MFC やラ
ンタイムは、ソースファイルでも引っかかるから気を付けて
……ソースファイルはインクルードしちゃいけない?
いけません。ヘッダーファイルには関数やクラスを使うために必要な情報
が、ソースファイルには関数やクラスが機能するための中身が入ってます。
使うのに必要なのは
ヘッダーファイル、ってことね
ま、拡張子で見分ければソースファイルかどうかはわかるでしょ
それに、置いてあるフォルダ違うし
あ、そっか。僕は【サブフォルダも探す】で API も MFC もランタイム
も、ヘッダーファイルもソースファイルも全部いっぺんに検索しちゃうか

その方がめんどそう……
あ、あと、 ifstream なんかの iostream 系は、 MSDN で調べると難しい
と思うよ。 std::ifstream は、ホントは std::basic_ifstream って名前だ
から
ホントはって? あ、 typedef !
そう、そういう別名になってるし、テンプレートって難しい機能も使われ
てるし。それに…… fstream って、一応ヘッダーファイルなんだけど
拡張子ないね
実は【ファイルから検索】だとこの拡張子ないのはうまくいかないんだよ

ホントだ、【ファイルから検索】に、検索するファイルの拡張子を選ぶの
があるんだね
他の開発環境だと、 fstream.h が本体で、 fstream からインクルードし
てる仕組みになってるんだけどね
それって VC がダメってこと?
そういうことになるのかなぁ……ま、こういうふうに iostream の場合に
は難しい部分があるけど、基本は MSDN か【ファイルから検索】で
ほいほい
で、ここまでが基本。ここからは応用
……難しい?
ちょっとね。まず、さっきの std::ifstream の例で、コンパイルエラー
が出ないようにしましょう。 fstream をインクルードして
この前と同じようにすればいいんだよね。じゃ、ここ

#include "stdafx.h"
#include <fstream>       // ここ。
#include "Debug.h"
#include "DebugDlg.h"

ビルドっ、エラー出ません!
さて今度は、 std::ifstream を CDebugDlg のメンバ変数として持たせて
みましょう。 DebugDlg.h を開いて

class CDebugDlg : public CDialog
{
    std::ifstream m_cIFStrm;    // ここに追加。
// あとは略。

ビルド、うおエラーが出た!

Debug.cpp
error C2653: 'std' : 識別子がクラス名でも名前空間名でもありません。
error C2146: 構文エラー : ';' が、識別子 'm_cIFStrm' の前に必要です。
error C2501: 'ifstream':識別名を宣言するのに、型が指定されていません

あれ? このエラーって、さっきの fstream をインクルードしてなかっ
た時に出たのと似てない?
ほとんど同じ。つまり、 std::ifstream なんてどこにもない! って言
われてるわけ
ええっ!? それ変!! ちゃんとインクルードしたもん
うん、 DebugDlg.cpp でインクルードしたはずだよね。ちょっとコンパイ
ルの話思い出してみて。コンパイルって、各ソースファイルごとにするって
言ったでしょ
うん、言った
ってことは、ヘッダーファイルの読み込みも、各ソースファイルごとにさ
れてなきゃいけないってこと。上のエラーよく見て。 Debug.cpp って書い
てあるでしょ
ホントだ! さっきのエラーは DebugDlg.cpp って書いてあったのに
さっきのエラーは DebugDlg.cpp をコンパイルしてたときに出たエラー、
今度のは Debug.cpp をコンパイルしてたときに出たエラー。 Debug.cpp の
インクルードしてる部分を見ると……

#include "stdafx.h"
#include "Debug.h"
#include "DebugDlg.h"

ここで DebugDlg.h をインクルードしてるでしょ
そっか! ここでも fstream をインクルードしないと、 DebugDlg.h の
中で std::ifstream 見つけても何か分かんないんだ!
そういうこと。このままだと、 Debug.cpp をコンパイルしてるときに 
std::ifstream の情報が全然入ってないから、 DebugDlg.h を読み込んだと
きに std::ifstream を理解できないわけ
はー、なるほど。ってことは

#include "stdafx.h"
#include <fstream>
#include "Debug.h"
#include "DebugDlg.h"

ってすればいいんだ。あ、質問! インクルードって、上から順番にして
く?
してくよ。だからその順番
なのね。だから

#include "stdafx.h"
#include "Debug.h"
#include "DebugDlg.h"
#include <fstream>

ビルド。あ、やっぱり同じエラーが出た。 Debugdlg.h をインクルードす
る前に fstream をインクルードしなきゃいけないわけね
そう、情報が先に入ってないと。あと、こういうふうに各ソースファイル
でインクルードするのは面倒だから、たいがいは stdafx.h の中でインク
ルードします

#endif // _AFX_NO_AFXCMN_SUPPORT
#include <fstream>    // ここ。

そっか、 stdafx.h って Debug.cpp からも DebugDlg.cpp からも インク
ルードされてるから
そういうこと。 <> で囲むようなの、つまりライブラリのヘッダーファイ
ルをインクルードするときには stdafx.h でした方がいいかな
そういえば、 <> で囲むのと "" の違いは?
 "" はプロジェクト内のファイル。 <> は、【ツール】−【オプション】
ダイアログの【ディレクトリ】−【インクルードファイル】見てみて
あ、さっき言ってた API や MFC の置いてあるフォルダ!
ここに指定してあるフォルダからインクルードファイルを探すのが、 <> 
でのインクルード
ってことは、これで好きな所にインクルードファイル置けるの?
もちろん。他の人が作ったライブラリを使う時には、そのライブラリの置
き場所をここで指定するようにね
 API とかのフォルダにコピーしちゃダメ?
駄目!!

/*
    Preview Next Story!
*/
そういうのダメなの?
ダメだって
なんで?
元々あるのと同じ名前のファイルがあったらまずいでしょうが
う”、そういえば
というわけで次回
< Version 6.05 プリプロセッサとマクロ >
につづく!
力業に頼らず、スマートに! これが優れたプログラマーへの近道
こんなだらだら教えてる人が何言ってんだか
はぅ
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。