使用ref传递的std :: ostream

时间:2014-07-11 13:15:10

标签: c++ visual-studio-2012 std

在我的代码中,我的类的init函数是这样的:

void MyApp::start(std::ostream & log_output)
{
    theLogOutput = log_output;
    // do stuff...
}

theLogOutput被声明为.h文件:

std::ostream theLogOutput;

但是编译器给了我这个错误:

Error 10 error C2248: 'std::basic_ostream<_Elem,_Traits>::operator =' : cannot access private member declared in class 'std::basic_ostream<_Elem,_Traits>'

2 个答案:

答案 0 :(得分:2)

std::ostream不可复制;它有可变状态,是 多态,这使复制和分配有问题。在 C ++ 11,它是可移动的,如果你想让调用者放弃所有 posession(但你必须明确地移动它)。大部分的 但是,时间,你不需要字符串的副本,也不是唯一的 所有权;在这些情况下,您将成员作为引用 好吧,或者如果班级必须支持作业,你就做了 成员指针,并获取参数的地址。

在您的情况下,由于您正在修改已存在的变量, 你需要使用指针;必须初始化引用,并且 一旦初始化,就无法重新安装。

答案 1 :(得分:1)

通过引用传递在这里工作正常,问题是theLogOutput = log_output会产生副本。

正如评论者指出的那样,std::ostream无法复制(因为它没有复制构造函数)。你可以做一些事情:

  • 如果log_output对象的生命周期是静态的(或者足够长),则可以使全局日志流成为std::ostream的指针,并使其保存所述对象的地址(即{ {1}},您可以考虑将流作为指针,以使意图更清晰)。例如,这适用于您在theLogOutput = &log_output中本地分配的std::coutstd::cin或任何std::ostream。请务必将文档中的生命周期要求说明为main
  • 在任何地方使用startApp来保持对单个流的共享引用。
  • 使用C ++ 11,您可以移动std::shared_ptr<std::ostream>

最后但同样重要的是,在std::ostream文件中声明全局变量并不是一个好主意。如果文件包含在多个翻译单元中,则由于多次定义符号而导致错误。最多应该在标题中声明.h,并且只在一个翻译单元(.cpp文件)中定义。