Question

I have read multiple questions and answers on that topic, but unfortunately none of them helped yet. I want to use the same debug file ouput in two classes A and B, where an instance of A creates an instance of B. I have something like:

class A {
public:
    A() : debug("debug.txt") { };
private:
    std::ofstream debug;
}

class B {
public:
    B(std::ofstream &ofs) : debug(ofs) { };
private:
    std::ofstream &debug;
}

and create an instance of it with

B *b = new B(debugUnderlying);

which works quite well. However, I now want to have an additional constructor to be able to use it without an ofstream. The object shall then open a new file. I got the point that, as I have a reference, I need to initialize it in the initialization list. I tried multiple things:

B() : debug() { debug.open("debug2.txt"); };

error: invalid initialization of non-const reference of type ‘std::ofstream& {aka std::basic_ofstream<char>&}’ from an rvalue of type ‘const char*’

or

B() : debug("debug2.txt") { };

error: value-initialization of reference type ‘std::ofstream& {aka std::basic_ofstream<char>&}’

or (quite clear, since I have a temporary object)

error: invalid initialization of non-const reference of type ‘std::ofstream& {aka std::basic_ofstream<char>&}’ from an rvalue of type ‘std::ofstream {aka std::basic_ofstream<char>}’

How can I do this? Thanks for any suggestions!

Was it helpful?

Solution

You may store a pointer and flag ownership:

class B {
   public:
   B() : stream(new ...), owner(true) {}
   B(std::ostream& s) : stream(&s), owner(false) {}
   ~B() { if(owner) delete stream; }
   private:
   std::ostream* stream;
   bool owner;
};

Note: I replaced ofstream with ostream.

OTHER TIPS

to fix your error:

B():debug(*(new std::ofstream("debug.txt"))){}

But: if you do so I guess you'll forget to delete...

So:

You better use a singleton to wrap the debug object

class Debug{
    std::ofstream debug;
    //private ctor, you can't create an object for this class outside
    Debug(const std::string& filename):debug(filename){}
public:
    //only way tou use this class is to call this method
    static Debug* Instance(){
            //the one and only Debug object, created at first use: 
        static Debug theObj("debug.txt");
        return &theObj;
    }
    //write method
    std::ostream& outstream(){
        return debug;
    }
};
//just for simplicity of use:
#define dbgout Debug::Instance()->outstream()

you can also define the macro like this:

#ifdef DEBUG
    #define dbgout Debug::Instance()->outstream()
#else
    // a release version won't create the debug file... 
    #define dbgout //
#endif    

now you can use it like this from anywhere in your code:

dbgout<<" put your " << "stream " <<" here ";
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top