Reputation: 2225
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
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
Reputation: 33607
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