【问题标题】:Reformulated previous status 3 query重新制定先前的状态 3 查询
【发布时间】:2012-11-04 16:36:38
【问题描述】:

好的,从C++ Process terminated with status 3 confusion 重新制定和合并到具有最少代码的单个文件,用“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/,以防这可能对遇到类似问题的其他人有所帮助。

【问题讨论】:

  • 以后,请考虑编辑您现有的问题,而不是创建一个新问题。
  • @Mike 抱歉,我以后会记住这一点。如果有帮助,我可以投票删除旧问题?

标签: c++ scope class-method class-reference


【解决方案1】:

logengine 是完全独立的。两者都无法与对方接触。

如果您希望engine 能够访问Logfile 的实例,例如可以通过setter 或Engine 的构造函数将其传递给engine

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;
}

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

然后您可以在Engine() 中使用它,例如:

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

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

【讨论】:

  • 谢谢!我没想到通过参数把它放进去。如果我确实创建了 Logfile 的全局实例,我将如何在没有参数的情况下从 Engine 构造函数访问它? (我在原始代码中将其设置为全局变量。)
  • @Jeremy 我添加了更多信息。
  • 太棒了!我非常感谢您对此进行了阐述。我现在有很多东西要研究。
【解决方案2】:

你需要让 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;
}

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

【讨论】:

  • 谢谢!我想我现在明白了。 'argc, *argv[]' 是干什么用的?
  • 在这种特殊情况下,因为它是我们正在处理的日志文件,所以很有可能它不应该被复制到想要使用它的类中。也许使用std::shared_ptr&lt;Logfile&gt; 会更好?
  • 我更新它以将日志引用传递给引擎,应该做同样的伎俩
猜你喜欢
  • 2014-10-04
  • 1970-01-01
  • 2020-10-28
  • 2021-11-09
  • 2022-01-18
  • 2015-06-19
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多