问题
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