3

OK、 C++ プロセスがステータス 3 の混乱で終了したことから、「ログ」参照を「cout」に置き換え、ファイルではなくコンソールに出力して、最小限のコードで単一のファイルに再構成および統合しました。code::blocks コンパイラで実行したところ、別のエラーが発生しましたが、同じ行で ['log' はこのスコープで宣言されていません] でした。独自のファイルにクラスがある場合、「ステータス3」でプログラムを閉じるだけです。

以前にスコープエラーに遭遇し、自分で修正し、理解したと思っていましたが、そうではないと思います...

#include <iostream>
#include <string> // Doesn't complain if this is not present...
using namespace std;

//------------------------------------------------------------
class Logfile {
public:
    bool LACT; // Is log file active?
    string value; // Data to be entered

    Logfile();
    ~Logfile();

    void entry(string value); // Make an entry
};

Logfile::Logfile() { // Constructor
    LACT = true;
    cout << "OPENED\n"; 
}

Logfile::~Logfile() {
    cout << "CLOSED\n";
}

void Logfile::entry(string value) {
    if ( LACT ) cout << value << endl;
}

//--------------------------------------------------
class Engine { // Constructor contains only code for this class right now
public :
    Engine();
};

この行でコンパイラがハングし、エラーが発生します。

Engine::Engine() {
    log.entry("Engine constructed"); // !Problem line!
}

問題は、別のクラス内から既存のオブジェクトのクラス メソッドを誤って呼び出していることだと考えていますか?

//--------------------------------------------------
int main()
{
    Logfile log;
    Engine engine;

    cout << "Hello world!" << endl;

    return 0;
}

問題の行を「//」すると、すべてが正常に実行され、コンソールに OPENED、Hello World!、CLOSED が出力されます。これは私が思っているよりもはるかに単純で初心者向けのものであると確信しているため、忍耐と時間をありがとう。

--

この質問をする最初の目的は (今ではわかります)、マルチファイル プログラムの任意の *.cpp ファイルからアクセスできる、グローバルに宣言されたオブジェクトを取得することでした。私はちょうどこの答えを見つけました:http://www.cplusplus.com/forum/beginner/3848/、これが同様の問題を抱えている他の人に役立つかもしれない場合に備えて。

4

2 に答える 2

1

logengine完全に分離しています。どちらも本質的に他方にアクセスできません。

engineのインスタンスにアクセスできるようにしたい場合は、たとえば、セッターまたはのコンストラクターを介してLogfile渡すことができます。engineEngine

Engine::Engine(Logfile& log) {
    log.entry("Engine constructed");
}

Logfileのグローバル インスタンス(のスコープ外)を持つことができる代替手段がありますmain。一般に、グローバル変数は悪い考えです。変数の有効期間は、可能な限り最小の範囲に縮小する必要があります。ただし、ログファイルは、この規則の合理的な例外として認められる場合があります。


もう少し詳しく説明すると、ログファイルにシングルトンを使用できます。シングルトンの使用は非常に論争の的となる問題です。シングルトンまたは二重チェックのロックを検索するだけで、危険に関する十分な議論が見つかります。

しかし、C++11 の登場により、事態はかなり安全になりました。新しい標準は、ローカル静的オブジェクトの初期化がスレッドセーフであることを保証します。これにより、次のようなことができます。

class Logfile {
public:
    static Logfile& instance();
    void entry(const string& value) { cout << value << '\n'; }
private:
    Logfile() { cout << "OPENED\n"; }
    ~Logfile() { cout << "CLOSED\n"; }
};

Logfile& Logfile::instance() {
    static Logfile log_file;
    return log_file;
}

コンストラクターは非公開になっていることに注意してください。を取得する唯一の方法Logfileinstance()関数を使用することです。これにはローカルの static がLogfileあるため、そのインスタンスは 1 つしか存在しません。

その後、次のように内部で使用できますEngine()

Engine::Engine() {
    Logfile::instance().entry("Engine constructed");
}

ただし、ここでも注意が必要です。たとえば、現時点では、VC2012 は、C++11 で必要とされるローカル スタティックのスレッドセーフな初期化をまだ実装していません。

于 2012-11-16T00:17:19.320 に答える
1

エンジン クラスにログ オブジェクトの場所を知らせる必要があります。したがって、次のようにコードを少し変更する必要があります。

class Engine { // Core system, contains main loop
public :
    Engine(Logfile& log);

private:
    Logfile& log_;
};

Engine::Engine(Logfile& log):log_(log)
{
    log_.entry("Engine constructed");
}

次に、メインから呼び出します。

int main(int argc, char *argv[]) 
{
  Logfile log;
  Engine engine(log);
  return 0;
}

string value;ところで:実際には Logfile クラスのメンバーを使用していないため、削除することを検討できます。

于 2012-11-16T00:20:58.627 に答える