Как правильно назначить cout статической ссылочной переменной ostream?
Я определяю такой класс:
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_;
};
Я определяю функцию конструкции как:
void StaticRuntimeContext::Construct() {
std::ostream& test = cout;
stdout1_ = cout;
stdout2_ = cout;
//stdout3_ = NULL;
stderr_ = cerr;
}
Я не могу понять, почему назначение cout для тестирования (std::ostream&) нормально для компиляции, но для остальных компилятор выдает сообщения об ошибках, например "stdout1_=cout". Сообщение об ошибке:
/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
Мне интересно, что я должен сделать, чтобы правильно назначить cout этим ссылочным переменным ostream. Спасибо!
5 ответов
Это связано с тем, что ссылки имеют семантику значений, а оператор = копирует объект вместо назначения новой ссылки.
Вместо ссылок вы должны определить статические указатели, назначить их в 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_;
void StaticRuntimeContext::Construct() {
stdout1_ = &cout;
stdout2_ = &cout;
stdout3_ = &cout;
stderr_ = &cerr;
}
РЕДАКТИРОВАТЬ: И вы должны добавить это в свой файл.cpp
std::ostream* StaticRuntimeContext::stdout1_ = NULL;
std::ostream* StaticRuntimeContext::stdout2_ = NULL;
std::ostream* StaticRuntimeContext::stdout3_ = NULL;
std::ostream* StaticRuntimeContext::stderr_ = NULL;
Этот код
std::ostream& test = cout;
это не задание, а построение новой ссылки. Это также может быть написано
std::ostream& test(cout);
без знака равенства. Эффект тот же.
Ссылка не может быть восстановлена после того, как она создана, поэтому она должна быть установлена на свое значение при создании. Статические члены также должны быть определены где-то, как в соответствующем файле.cpp. Просто установите значения там:
std::ostream& StaticRuntimeContext::stdout1_ = std::cout;
std::ostream& StaticRuntimeContext::stdout2_ = std::cout;
std::ostream& StaticRuntimeContext::stdout3_ = std::clog;
std::ostream& StaticRuntimeContext::stderr_ = std::cerr;
Вы должны использовать указатель, потому что ссылки не позволяют перепривязывать и std::ostream
не копируемый
В C++ ссылочные переменные должны быть инициализированы при их объявлении.
действует:
int x;
int& foo = x;
Недействительным:
int x;
int& foo;
foo = x;
Я не могу понять, почему назначение cout для тестирования (std::ostream&) нормально для компиляции
Потому что это не задание; это инициализация.