How should I correctly assign cout to a static ostream reference variable?

会有一股神秘感。 提交于 2019-12-09 18:27:39

问题


I'm defining a class like this:

class StaticRuntimeContext {
 public:
  enum Verbosity {
    kHIGH,
    kMEDIUM,
    kLOW,
    kSILENT
  };
  static void Construct();
  static std::ostream& stdout1() {return stdout1_;}
  static std::ostream& stdout2() {return stdout2_;}
  static std::ostream& stdout3() {return stdout3_;}
  static std::ostream& stderr() {return stderr_;}
 protected:
 private:
  static std::ostream& stdout1_;
  static std::ostream& stdout2_;
  static std::ostream& stdout3_;
  static std::ostream& stderr_;
};

I'm defining the construct function as:

void StaticRuntimeContext::Construct() {
  std::ostream& test = cout;
  stdout1_ = cout;
  stdout2_ = cout;
  //stdout3_ = NULL;
  stderr_ = cerr;
}

I cannot understand why assigning cout to test (std::ostream&) is OK to compile but the compiler produces error messages for the rest like "stdout1_=cout". The error message is:

/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/ios_base.h:791:5: error: ‘std::ios_base& std::ios_base::operator=(const std::ios_base&)’ is private

I'm wondering what I should do to correctly assign cout to these ostream reference variables. Thanks!


回答1:


It's because references have value semantics, and the operator = is copying the object instead of assigning a new reference.

Instead of references you should define static pointers, assign them in Construct, and return references in your accessors

  static std::ostream& stdout1() {return *stdout1_;}
  static std::ostream& stdout2() {return *stdout2_;}
  static std::ostream& stdout3() {return *stdout3_;}
  static std::ostream& stderr()  {return *stderr_;}
 protected:
 private:
  static std::ostream* stdout1_;
  static std::ostream* stdout2_;
  static std::ostream* stdout3_;
  static std::ostream* stderr_;

void StaticRuntimeContext::Construct() {
  stdout1_ = &cout;
  stdout2_ = &cout;
  stdout3_ = &cout;
  stderr_ = &cerr;
}

EDIT: And you must add this in your .cpp file

std::ostream* StaticRuntimeContext::stdout1_ = NULL;
std::ostream* StaticRuntimeContext::stdout2_ = NULL;
std::ostream* StaticRuntimeContext::stdout3_ = NULL;
std::ostream* StaticRuntimeContext::stderr_ = NULL;



回答2:


This code

std::ostream& test = cout;

is not an assignment, but a construction of a new reference. It can also be written

std::ostream& test(cout);

without the equal sign. The effect is the same.

A reference cannot be rebound once it is created, so it must be set to its value when created. The static members also have to be defined somewhere, like in the corresponding .cpp file. Just set the values there:

 std::ostream& StaticRuntimeContext::stdout1_ = std::cout;
 std::ostream& StaticRuntimeContext::stdout2_ = std::cout;
 std::ostream& StaticRuntimeContext::stdout3_ = std::clog;
 std::ostream& StaticRuntimeContext::stderr_  = std::cerr;



回答3:


In C++ reference variables must be initialized when they are declared.

valid:

int x;
int& foo = x;

Invalid:

int x;
int& foo;
foo = x;



回答4:


You need to use a pointer, because references do not allow rebind and std::ostream is noncopyable.




回答5:


I cannot understand why assigning cout to test (std::ostream&) is OK to compile

Because that isn't assignment; it's initialization.



来源:https://stackoverflow.com/questions/8070537/how-should-i-correctly-assign-cout-to-a-static-ostream-reference-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!