user1285419
user1285419

Reputation: 2225

why static ofstream doesn't work

I am developing a program in c++ with lots of file io operation. I have defined a static ofstream in a common header so that it is accessible everywhere in the project. The structure of the codes are list as following: all common variable are defined in com.h, test.h and test.cpp are for a class called OPClass, main.cpp carry the main program

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

As you can see, the static ofstream was named as out and will be called in the main program and in the class. I am using mingw32 and didn't see any problem on compilation or upon running. But seems that only the information in runmain() will be written to the output file. Any other message written to that file in the class never appear in the output file. Why's that and how can I written a common file stream so everywhere in the project can access that? Thanks.

Upvotes: 2

Views: 5670

Answers (2)

Brent Writes Code
Brent Writes Code

Reputation: 19603

Preemptive statement: You should accept @HostileFork's answer.

Just as an addendum, an easy way to show what's happening is to print out the address of out whenever you try to use it.

If you add these couple statements:

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

And:

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

You'll notice that the two print statements for out display two different addresses. This should tell you that you're actually getting two instances of out created as two distinct variables. The methods in your OPClass are trying to write to a completely different output stream. It has to do with the way you're using static in a global context; it doesn't behave like you think it does. In a global context, declaring something static binds it to the local scope of the file it's in.

Upvotes: 1

Each compilation unit is getting its own ss and out. Hence there is a different instance of them seen by main.cpp than by test.cpp.

You don't really need static here. To address this, rather than declaring the variables and their allocations in the header file you need to merely prototype them using the extern keyword.

#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

Where you actually put your declarations is up to you, just make sure it's only in one place. That could be a com.cpp file or you could stick it in main.cpp if that's appropriate for your project.

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

Not that global variables like this are a good idea, anyway...

Upvotes: 3

Related Questions