8

我正在定义一个这样的类:

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 分配给 test (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 引用变量。谢谢!

4

5 回答 5

10

这是因为引用具有值语义,并且运算符 = 正在复制对象而不是分配新的引用。

您应该定义静态指针,而不是引用,在 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;
于 2011-11-09T19:39:52.183 回答
2

这段代码

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;
于 2011-11-09T20:23:02.290 回答
0

在 C++ 中,引用变量必须在声明时进行初始化。

有效的:

int x;
int& foo = x;

无效的:

int x;
int& foo;
foo = x;
于 2011-11-09T19:42:23.213 回答
0

您需要使用指针,因为引用不允许重新绑定并且不可std::ostream复制。

于 2011-11-09T19:44:41.170 回答
0

我不明白为什么将 cout 分配给 test (std::ostream&) 可以编译

因为那不是任务;这是初始化。

于 2011-11-09T20:13:03.037 回答