【问题标题】:why static ofstream doesn't work为什么静态 ofstream 不起作用
【发布时间】:2012-04-21 04:00:10
【问题描述】:

我正在用 C++ 开发一个包含大量文件 io 操作的程序。我在公共标头中定义了一个静态 ofstream,以便在项目中的任何地方都可以访问它。代码结构如下:所有公共变量都定义在com.h中,test.h和test.cpp是针对一个叫OPClass的类,main.cpp承载主程序

COM.H:

#ifndef __CLCOM__
#define __CLCOM__
#include <sstream>
#include <fstream>
#include <iostream>

using namespace std;

static ofstream out;
static stringstream ss;

#endif

TEST.H:

#ifndef __CL__
#define __CL__
#include <iostream>
#include <fstream>
#include "com.h"

using namespace std;

class OPClass
{
  public:
   void run(void);
   void show(ostream &o) const;
};
#endif

TEST.CPP:

#include "com.h"
#include "test.h"

void OPClass::run(void)
{
  out << "Here is run()" << endl;
  show(out);
}

void OPClass::show(ostream &o) const
{
  o << "hello!" << endl;
}

MAIN.CPP:

#include "com.h"
#include "test.h"

void runmain(void)
{
  OPClass op;
  out.open("output.txt", ios::out | ios::trunc);
  out << endl << "State changed!" << endl;
  op.run();
  if (out.is_open()) out.close();
}

int main(int argc, char* argv[])
{
  runmain();
  return  0;
}

如您所见,静态 ofstream 被命名为 out,将在主程序和类中调用。我正在使用 mingw32 并且在编译或运行时没有看到任何问题。但似乎只有 runmain() 中的信息会被写入输出文件。写入类中该文件的任何其他消息永远不会出现在输出文件中。为什么会这样,我如何编写一个通用文件流,以便项目中的任何地方都可以访问它?谢谢。

【问题讨论】:

    标签: c++ ofstream


    【解决方案1】:

    每个编译单元都有自己的ssout。因此,main.cpp 与 test.cpp 看到的实例不同。

    你在这里并不需要静态。要解决这个问题,您只需使用 extern 关键字对它们进行原型设计,而不是在头文件中声明变量及其分配。

    #ifndef __CLCOM__
    #define __CLCOM__
    #include <sstream>
    #include <fstream>
    #include <iostream>
    
    // Note: don't put "using" statements in headers
    // use fully qualified names instead 
    extern std::ofstream out;
    extern std::stringstream ss;
    
    #endif
    

    您实际将声明放在哪里取决于您,只要确保它只在一个地方即可。这可能是一个 com.cpp 文件,或者如果这适合您的项目,您可以将其粘贴在 main.cpp 中。

    std::ofstream out;
    std::stringstream ss;
    

    无论如何,像这样的全局变量并不是一个好主意......

    【讨论】:

    • 非常感谢。有用。我只有一个问题,为什么我们不应该在标题中放置“使用”语句?无论如何,我可以把它放在实现中(即cpp)吗?谢谢
    • 欢迎您。 using 在实现文件中很好,但在标头中被认为是一种不好的做法……这是关于为什么会这样的问答:stackoverflow.com/questions/2232496/…
    【解决方案2】:

    先发制人的声明:您应该接受@HostileFork 的回答。

    作为附录,显示正在发生的事情的一种简单方法是在尝试使用时打印出out 的地址。

    如果你添加这两个语句:

    void OPClass::run(void)
    {
      cout << "Address of 'out' = " << &out << endl;
      out << "Here is run()" << endl;
      show(out);
    }
    

    还有:

    void runmain(void)
    {
      cout << "Address of 'out' = " << &out << endl; 
      OPClass op;
      out.open("output.txt", ios::out | ios::trunc);
      out << endl << "State changed!" << endl;
      op.run();
      if (out.is_open()) out.close();
    }
    

    您会注意到out 的两个打印语句显示两个不同的地址。这应该告诉您,您实际上将两个 out 实例创建为两个不同的变量。 OPClass 中的方法正在尝试写入完全不同的输出流。这与您在全球范围内使用static 的方式有关;它的行为不像你想象的那样。在全局上下文中,声明 static 会将其绑定到它所在文件的本地范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-03
      • 2014-06-29
      • 2016-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多