static変数を使用した時に起きた問題。

[戻る]
にいがた 2005/05/04(水) 14:58:16
【開発環境】WindowsXP VC++6.0 MFC アプリケーション(EXE)
staticで宣言したグローバル変数ostream finを利用してシステム全体のログをファイル
に吐き出す処理をしていますが、何故かファイルを開く処理をする箇所でしか書き込む
ことが出来ず、その他の処理ではログが書き出せません。
みなさんはログファイルを出力する処理で、どのように変数を宣言をしているのです
か?
教えてください。

iijima 2005/05/04(水) 20:03:32
staticキーワードをつけて宣言した変数は、それが含まれるコンパイル単位(cppファイ
ル)内でのみ有効です。
ご説明だけではどのように使われているのか分かりませんが、もし、複数のコンパイル
単位で同時にstatic変数としてfinを宣言していたとすれば、finからログを吐き出す処
理を書いたコンパイル単位内での処理結果しか吐き出されないのは当然です。

// 参考:このような構造になっていませんか?

// a.cpp
#include <sstream>

static std::ostringstream fin; // "a.cpp"内だけで有効

void f()
{
    fin << "f() has been called." << std::endl;
}


// b.cpp
#include <sstream>
#include <iostream>

static std::ostringstream fin; // "b.cpp"内だけで有効

void g()
{
    fin << "g() has been called." << std::endl;
}

void display_log() // ログの吐き出し
{
    std::cout << fin.str();
}


// exam.cpp
extern void f();
extern void g();
extern void display_log();

int main()
{
    f();
    g();
    display_log();
}

/* 実行結果("f()"の呼び出しは記録されていない):
g() has been called.
*/

VC初心者A 2005/05/04(水) 21:31:45
[[解決]]
iijimaさん、親切な対応ありがとうございます。
staticで変数を宣言するときは、その宣言したh、またはcppファイル中で全て処理を書
かなければいけないという事ですよね?
理解いたしました。

iijima 2005/05/04(水) 23:20:48
> staticで変数を宣言するときは、その宣言したh、またはcppファイル中で全て処理を> かなければいけないという事ですよね?

ひとつの翻訳単位内だけで使いたい(他の翻訳単位からは参照されたくない)変数につい
て、staticキーワードをつけて定義するということです。
なお、C++言語では、staticでなく"無名名前空間"を使うことが推奨されています。

ある変数を複数の翻訳単位で共用したいのであれば、どれかひとつの翻訳単位でグロー
バル変数(staticをつけない)を「定義」し、その変数を参照したい他の翻訳単位では、
externキーワードを使ってその変数を「宣言」します。

前回の例をそのように書き直すと次のようになります。
違いをよく吟味してください。

// a.cpp
#include <sstream>

std::ostringstream fin; // 定義:他の翻訳単位から参照可

void f()
{
    fin << "f() has been called." << std::endl;
}


// b.cpp
#include <sstream>
#include <iostream>

extern std::ostringstream fin; // 宣言:他の翻訳単位で定義されている変数

void g()
{
    fin << "g() has been called." << std::endl;
}

void display_log()
{
    std::cout << fin.str();
}


// exam.cpp
extern void f();
extern void g();
extern void display_log();

int main()
{
    f();
    g();
    display_log();
}

/* 実行結果
f() has been called.
g() has been called.
*/

VC初心者A 2005/05/04(水) 23:43:16
staticとexternの使い方について完全に理解しました。
iijimaさん、ありがとうございました。

古いスレッドには追加発言できません。