3

好的,从C++ 进程重新制定和合并,以状态 3 混淆终止到具有最少代码的单个文件,用“cout”替换我的“日志”引用,打印到控制台而不是文件。我通过 code::blocks 编译器运行它并得到一个不同的错误,但是对于同一行 ['log' is not declared in this scope]。当我在自己的文件中有类时,它只是以“状态 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

log并且engine是完全分开的。两者都无法访问对方。

如果您希望engine能够访问 的实例,例如可以通过 setter 或通过的构造函数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;
}

请注意,构造函数现在是私有的。获得 a 的唯一方法Logfile是通过instance()函数,因为它有一个本地 static Logfile,所以永远只有一个实例。

然后你可以在里面使用它Engine()

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

不过,您仍然需要在这里小心。比如此时VC2012还没有实现C++11所要求的局部静态的线程安全初始化。

于 2012-11-16T00:17:19.320 回答
1

您需要让 Engine 类知道日志对象在哪里。所以你需要修改你的代码:

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

private:
    Logfile& log_;
};

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

现在你从 main 调用它:

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

顺便说一句:您并没有真正string value;在 Logfile 类中使用成员,您可以考虑将其删除。

于 2012-11-16T00:20:58.627 回答