覆盖“operator<<”的问题在类中派生自“ostream”

时间:2009-09-04 20:38:09

标签: c++

我想基于“ostream”创建一个类,它会执行一些自动格式化以生成逗号或制表符分隔值文件。我的想法是覆盖“operator<<”让它在每个值之前插入一个分隔符(除了行的开头和结尾),并在写入之前引用字符串。在最重要的“运营商<<”中方法,我想调用基类的方法,但我不能让它正常工作。

这是一个例子(用g ++ 4.3.3编译):

#include <iostream>
#include <ostream>
#include <string>

using namespace std;

class MyStream: public ostream
{
public:
  MyStream(ostream& out): ostream(out.rdbuf()) {}

  template <typename T> MyStream& operator<<(T value)
  {
    ostream::operator<<('+');
    ostream::operator<<(value);
    ostream::operator<<('+');
    return *this;
  }
};

template<> MyStream& MyStream::operator<< <string>(string value)
{
  ostream::operator<<('*');
  ostream::write(value.c_str(), value.size()); // ostream::operator<<(value);
  ostream::operator<<('*');
  return *this;
}

int main()
{
  MyStream mystr(cout);
  mystr << 10;
  cout << endl;
  mystr << "foo";
  cout << endl;
  mystr << string("test");
  cout << endl;
  return 0;
}

两个“运营商&lt;&lt;”方法(模板和特化)是以不同于其他方式处理字符串的方式。但是:

  1. 字符('+'/'*')打印为数字而不是字符。
  2. C-String“foo”打印为内存地址(我认为)。
  3. 如果“注释”行与注释部分交换,编译器会抱怨“没有匹配函数来调用'MyStream :: operator&lt;&lt;(std :: string&amp;)'”,尽管我认为我明确地调用了基类方法。
  4. 我做错了什么?非常感谢任何帮助。

2 个答案:

答案 0 :(得分:5)

打印字符串和字符的operator<<重载是自由函数。但是当您强制调用成员函数时,您将强制它们转换为ostream中声明的成员函数的一个候选者。对于'*',它可能会使用int重载,对于"foo",它可能会使用const void*重载。

我不会继承ostream,而是将ostream存储为参考成员,然后从operator<<委托给它。我也不会让operator<<成为一个成员,而是一个免费的功能模板,而不是专门的,但会使operator<<std::string的{​​{1}}重载。

答案 1 :(得分:2)

以下内容可能有效:

包括

#include <ostream>
#include <string>

using namespace std;

class MyStream: public ostream
{
public:
    MyStream(ostream& out): ostream(out.rdbuf()) {}

    template <typename T> MyStream& operator<<(const T& value)
    {
        (ostream&)*this << '+' << value << '+';
        return *this;
    }
    MyStream& operator<< (const string& value)
    {
        (ostream&)*this << '*' << value << '*';
        return *this;
    }
    MyStream& operator<< (const char* cstr)
    {
        (ostream&)*this << '(' << cstr << ')';
        return *this;
    }
};