0

I'm trying to create class that overwrite cout to be able to write the same massage on multiple channels(standard output, file etc)

class myClass{
private:
   ostream &str;
   ostringstream ostr;
public:
  myClass(ostream &str1){ str=str1; }
  ............
}

The problem is that I'm trying to use a single instance of the object in all my file:

static myClass _cout(cout);

There is anotoher solution beside static or external? I was thinking about a singleton class but I want that my variable to be global and accessible for all the h and cpp file.

userP
  • 1
  • 1
    a singleton is a global, hence its not clear why thats a "but" – 463035818_is_not_an_ai Jan 21 '22 at 10:08
  • 1
    The problem you ask about is not the only problem in the shown code. But as for the question itself, all `static` variables in *namespace scope* (as it's called) will have [internal linkage](https://en.cppreference.com/w/cpp/language/storage_duration#Internal_linkage) which means they will be local to the current [translation unit](https://en.wikipedia.org/wiki/Translation_unit_(programming)). – Some programmer dude Jan 21 '22 at 10:09
  • One stupid way of doing that is to store the address of the static variable in another global variable (of type pointer) and then you can have access to that static var from the functions of other translation units using the address. But as I said, it's pointless. – digito_evo Jan 21 '22 at 10:13
  • Under linux you might solve that with `tee`. No need to change your programme then. Under windows, it's pretty easy to re-implement `tee`, so that might be an option as well. – Aconcagua Jan 21 '22 at 10:19
  • Under linux you might as well `dup(STDOUT_FILENO)`, close the original file descriptor and replace it with the writing end of a `pipe` – then read from that pipe and forward all data to whereever you need. – Aconcagua Jan 21 '22 at 10:26
  • 1
    btw your constructor should be `myClass(ostream &str1) : str(str1) {}` – 463035818_is_not_an_ai Jan 21 '22 at 10:26
  • Not identical, but similar; with a few adjustments this might be suitable for you, too: https://stackoverflow.com/questions/243696/correctly-over-loading-a-stringbuf-to-replace-cout-in-a-matlab-mex-file – Aconcagua Jan 21 '22 at 10:43

1 Answers1

0

The standard way of doing this is external - the global variable is external in your header file and it is included in exactly one source file (translation unit). All objects link with this one.

Another standard way of doing this is to have a static member function that creates a new object on the first call and then returns that same object on all subsequent calls.

class myClass{
private:
   ostream &str;
   ostringstream ostr;
   static myClass *instance;
   myClass(ostream &str1){ str=str1; }
public:
   static myClass *GetInstance(ostream &str1);
}

Look at https://refactoring.guru/design-patterns/singleton/cpp/example for a full example with all the right definitions.

mmomtchev
  • 2,497
  • 1
  • 8
  • 23
  • That variant of singleton requires a stream to get passed to any time we need an instance – how would we handle passing different streams? I'd rather prefer a separate `initInstance` plus a *parameterless* `instance` function. A more modern pattern than the one in the link is `MyClass& instance() { static MyClass theInstance; return theInstance; }` – guaranteed to be thread-safe by the standard (thus coming with a bit of overhead, though). – Aconcagua Jan 21 '22 at 14:42
  • Passing a reference is basically free - it is a 64 bit word. But yes, your approach is valid too. – mmomtchev Jan 21 '22 at 15:09
  • It's not about costs, it's about *usability*. Still having to pass an (any arbitrary) stream even though the instance has been constructed since long is inconvenient, may come up with a surprise (doesn't print to `std::out` even though that one has been passed to – because of having been called earlier with `std::err`) and finally is, well, unaesthetic... – Aconcagua Jan 21 '22 at 15:14