将std :: ostream的子节点传递给需要std :: ostream *的库

时间:2011-03-13 12:44:19

标签: c++ logging polymorphism ostream

我有一个派生自std :: ostream的类(用于记录)。剥离,看起来像这样:

class bsgs : public std::ostream {
public:

  bsgs(const std::string& msg = "") {
    // some setup work
  }

  ~bsgs() {
    // some cleanup work
  }

  template<typename T>
  bsgs& operator<<(const T& rhs) {
    os << rhs;
    return *this;
  }

private:
  std::ostringstream os;
};

我写了这个类来做一些我需要的特殊事情,比如delta压缩。不幸的是,它不起作用。我需要将它传递给第三方库(有源,但公平 大而混乱)提供“set_out”函数来将其输出定向到std :: ostream。该 set_out函数原型就是这样:

void set_out(std::ostream *out=0, int level=1);

如果我将其称为:

set_out(&std::cout, 3);

set_out(&std::cerr, 5);

我完全得到了预期的行为。但是,如果我写:

bsgs logger;
set_out(&logger, 3);

我可以看到记录器的构造函数和析构函数按预期调用,但永远不会调用operator<<。我不确定为什么,我希望这是一个简单的问题。如果我能解决这个问题,那我就完全了。

有谁知道到底发生了什么?问题似乎是图书馆不知道我正在传递指向bsgs而不是std::ostream的指针,而是修复库以接受比{{1}更广泛的对象看起来它可能涉及触摸500多行代码,我想避免使用。

~~~~~~~~~~~~~~

编辑#1:我不确定它是否重要,但是库在其类层次结构的顶部有一个虚拟std::ostream *函数,该函数已实现(就我所见而言相同)在不同的子类中。如果 I 正在编写库,我会使set_out() = 0;成为一个(非虚拟)模板函数,并为std :: ostream提供专门化,但让用户提供他们喜欢的任何内容因为他们定义了一个可用的set_out。对库进行此更改看起来将是一个可靠的半天编辑。也许有一种更简单的方法?

2 个答案:

答案 0 :(得分:1)

没有线索你传递了一个指向bsgs的指针 - 你没有覆盖虚函数,没有涉及多态。

您可能会发现实现streambuf并替换与流关联的流缓冲区(ostream::rdbuf)是一种更可行的解决方案。

答案 1 :(得分:1)

您可以随时使用

std::ostringstream os;
set_out(&os, 3);

如果您想从ostream派生,只需创建自己的streambuf实现,这是虚拟的,并创建像

这样的流
std::ostream stream(new myStreamBuf);
set_out(&stream, 3);