Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Inheritance 如何从std::ostream继承?_Inheritance_Stl_Ostream - Fatal编程技术网

Inheritance 如何从std::ostream继承?

Inheritance 如何从std::ostream继承?,inheritance,stl,ostream,Inheritance,Stl,Ostream,我一直在谷歌搜索,我就是找不到一个简单的答案。它应该很简单,就像STL一般一样 我想定义从std::ostream公开继承的MyOStream。假设每次有东西写入流时,我都要调用foo() class MyOStream : public ostream { public: ... private: void foo() { ... } } 我知道ostream的公共接口是非虚拟的,那么如何实现呢? 我希望客户端能够同时使用运算符组合,而不是继承。您的类包含“包装”一个ostream

我一直在谷歌搜索,我就是找不到一个简单的答案。它应该很简单,就像STL一般一样

我想定义从std::ostream公开继承的MyOStream。假设每次有东西写入流时,我都要调用foo()

class MyOStream : public ostream {
public:
  ...
private:
   void foo() { ... }
}
我知道ostream的公共接口是非虚拟的,那么如何实现呢?
我希望客户端能够同时使用运算符组合,而不是继承。您的类包含“包装”一个ostream&,并转发给它(在调用foo()之后)。

不幸的是,这不是一个简单的问题。您应该从中派生的类是
basic
类,例如
basic\u ostream
。但是,从流派生可能不是您想要的,您可能希望从流缓冲区派生,然后使用该类实例化现有的流类


整个领域都很复杂,但有一本关于它的好书,我建议您在进一步研究之前先看一看。

我不知道这是否是正确的解决方案,但我以这种方式继承了std::ostream。它使用从std::basic_streambuf继承的缓冲区,一次获取64个字符(如果刷新,则更少),并将它们发送到通用的putChars()方法,在该方法中完成数据的实际处理。它还演示了如何提供用户数据

#包括
#包括
#包括
//#定义调试
类MyData
{
//示例数据类,未使用
};
类MyBuffer:public std::basic_streambuf
{
公众:
内联MyBuffer(MyData数据):
数据(数据)
{
setp(buf,buf+buf_尺寸);
}
受保护的:
//当缓冲区已满时调用。如果
//如果未使用缓冲区,则每
//将字符放入流的时间。
内联虚拟int溢出(int c=Traits::eof())
{
#ifdef调试

实现类似效果的另一个可行方法是使用模板和合成

class LoggedStream {
public:
  LoggedStream(ostream& _out):out(_out){}
  template<typename T>
  const LoggedStream& operator<<(const T& v) const {log();out << v;return *this;}
protected:
  virtual void log() = 0;
  ostream& out;
};

class Logger : LoggedStream {
  void log() { std::cerr << "Printing" << std::endl;}
};

int main(int,char**) {LoggedStream(std::cout) << "log" << "Three" << "times";}
类日志数据流{
公众:
LoggedStream(ostream&_out):out(_out){
模板

const LoggedStream&operator我在思考如何做同样的事情,我发现其实没那么难。 基本上,只需对ostream和streambuf对象进行子类化,并以其自身作为缓冲区来构造ostream。发送到流的每个字符都将调用std::streambuf中的虚拟溢出()。为了适合您的示例,我只制作了一个foo()函数并调用了它

#include <iostream>

struct Bar :  private std::streambuf , public std::ostream
{
    Bar() : std::ostream(this) {}

private:
    int overflow(int c) override
    {
        foo(c);
        return 0;
    }


    void foo(char c)
    {
        std::cout.put(c);

    }
};

int main()
{
    Bar b;
    b<<"Look a number: "<<std::hex<<29<<std::endl;

    return 0;
}
#包括
结构栏:私有std::streambuf,公共std::ostream
{
Bar():std::ostream(this){}
私人:
int溢出(int c)覆盖
{
傅(丙),;
返回0;
}
void foo(字符c)
{
标准:电流输出(c);
}
};
int main()
{
b栏;

B请发布一些代码,说明如何使用现有的组合,这并不总是最好的解决方案,就像继承不总是最好的解决方案一样。ostream为它实现了十几个重载运算符,你不会期望有人真的重写ostream的所有公共接口,只是为了给类添加一个小功能。还有人们写他们自己的歌剧的问题本打算去查阅我的这本书,但你让我不用这么做+1@anon我在网上找不到任何关于ASTRAIM的参考。它是什么?STL可能很简单,但这只是C++标准库的一部分。IOFSUSTORE库与(曾经)没有任何关系。STL.STL基本上是contianers+迭代器+算法。Iostreams、locale和所有来源完全不同的东西,通常使用起来很麻烦;)这不支持像
hex
endl
这样的东西为什么不支持?
t
将得到
std::hex
的类型。@ElazarLeibovich:它适用于
std::hex
但不适用于
std::endl
std::flush
(可能还有其他一些)。这是因为它无法将T解析为适当的函数类型。将以下内容添加到
LoggedStream
可解决此问题:
LoggedStream const&operator@LokiAstari你知道怎么做并且仍然支持
std::endl
?工作非常完美!应该是公认的答案,尽管这是一个老问题。我同意ZXcvbnM,这应该是公认的答案。公认的答案包含有用的参考资料,但并没有真正提供解决方案。Ben提供了一个简单的工作解决方案。+1.在寻找了这么长时间后,我终于找到了一个解决方案,这应该是人们所说的公认答案。非常感谢!经过这么长时间,我终于找到了解决方案在这个答案中,答案是肯定的。我想人们通常不希望客户端使用
Bar
作为
std::streambuf
。在这种情况下,私有继承似乎是一种方式:
class Bar:private std::streambuf,public std::ostream{}
这是有缺陷的。您正在向尚未构造的缓冲区传递指针,因为基类是在数据成员之前初始化的。有关详细信息,请参阅。
#include <iostream>

struct Bar :  private std::streambuf , public std::ostream
{
    Bar() : std::ostream(this) {}

private:
    int overflow(int c) override
    {
        foo(c);
        return 0;
    }


    void foo(char c)
    {
        std::cout.put(c);

    }
};

int main()
{
    Bar b;
    b<<"Look a number: "<<std::hex<<29<<std::endl;

    return 0;
}