Как правильно назначить cout статической ссылочной переменной ostream? - PullRequest
3 голосов
/ 09 ноября 2011

Я определяю класс следующим образом:

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 ]

6 голосов
/ 09 ноября 2011

Это потому, что ссылки имеют семантику значений, и оператор = копирует объект вместо назначения новой ссылки.

Вместо ссылок вы должны определить статические указатели, назначить их в 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;
}

EDIT: И вы должны добавить это в свой .cpp файл

std::ostream* StaticRuntimeContext::stdout1_ = NULL;
std::ostream* StaticRuntimeContext::stdout2_ = NULL;
std::ostream* StaticRuntimeContext::stdout3_ = NULL;
std::ostream* StaticRuntimeContext::stderr_ = NULL;
1 голос
/ 10 ноября 2011

Этот код

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;
0 голосов
/ 10 ноября 2011

Я не могу понять, почему назначение cout для проверки (std :: ostream &) можно использовать при компиляции

Поскольку не является назначением ;это инициализация.

0 голосов
/ 09 ноября 2011

Вам нужно использовать указатель, потому что ссылки не позволяют повторное связывание и std::ostream не может быть скопировано.

0 голосов
/ 09 ноября 2011

В C ++ ссылочные переменные должны быть инициализированы при их объявлении.

Действительно:

int x;
int& foo = x;

Invalid:

int x;
int& foo;
foo = x;
...