Я определяю класс следующим образом:
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. Спасибо!
Ответ 1 · рейтинг 10 · Gabriel Cuvillier
Это связано с тем, что ссылки имеют семантику значений, а оператор = копирует объект вместо назначения новой ссылки.
Вместо ссылок вы должны определять статические указатели, назначать их в 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;
Ответ 2 · рейтинг 2 · Bo Persson
Этот код
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;