代码之家  ›  专栏  ›  技术社区  ›  Kazoom

ofstream或ostream类型如何将所有类型强制转换为字符串?

  •  3
  • Kazoom  · 技术社区  · 15 年前

    任何系统定义的用户类型都将转换为字符串或char*?

    比如cout<<4<<“你好,世界”;

    工作得很好,这是怎么做到的?每种类型的<<运算符是否都超载?有没有一种方法可以通过一个通用重载函数来实现它?我的意思是,我可以只使用一个带一个参数(比如void*)的重载运算符方法,然后在该方法内部决定如何将整数类型转换为字符*

    如果我使用模板(即

    class UIStream
    {
    private:
     ofstream stream;
    public:
     UIStream();
     ~UIStream();
     template <typename T>
     UIStream& operator << (const T);
    };
    

    所以这个作品

     UIStream my_stream;
     my_stream<<"bcd"<10;
    

    但是当我这样做的时候它会给编译器带来错误

    my_stream <<endl;
    

    错误C2678:二进制“<<':找不到接受“uistream”类型的左侧操作数的运算符(或没有可接受的转换)

    std::endl也不是一种对象类型吗?

    4 回复  |  直到 15 年前
        1
  •  11
  •   Community CDub    7 年前

    在重新阅读你的问题后(由于在本文中的评论 answer )我已经意识到你想要的不仅仅是转换成字符串(我在另一个答案中的假设 here 而不是转发到流的内部。

    现在,你想要实现的并不简单,而且在大多数情况下可能是杀伤力过大。在执行 [make_string][3] 我有(转发到内部 ostringstream )我不允许通过操纵器。如果用户想添加新行(我们在Linux下开发),他们只需传递一个\n'字符。

    你的问题是转发操纵器( std::hex , std::endl ……)您的运算符<<定义为获取类型t的常量实例,但操纵器是函数指针,编译器无法将其与方法匹配。

    操纵器是在 std::basic_ostream 模板。这个 basic_ostream 模板和 ostream 类定义为:

    template <typename TChar, typename TTraits = char_traits<TChar> >
    class basic_ostream;
    
    typedef basic_ostream<char> ostream;
    // or
    // typedef basic_ostream<wchar_t> if using wide characters
    

    然后,可以传递给std::ostream的可能的操纵器是:

    typedef std::ostream& (*manip1)( std::ostream& );
    
    typedef std::basic_ios< std::ostream::char_type, std::ostream::traits_type > ios_type;
    typedef ios_type& (*manip2)( ios_type& );
    
    typedef std::ios_base& (*manip3)( std::ios_base& );
    

    如果要接受操纵器,则必须在类中提供该重载:

    class mystream
    {
    //...
    public:
       template <typename T> 
       mystream& operator<<( T datum ) {
          stream << datum;
          return *this
       }
       // overload for manipulators
       mystream& operator<<( manip1 fp ) {
          stream << fp;
          return *this;
       }
       mystream& operator<<( manip2 fp ) {
          stream << fp;
          return *this;
       }
       mystream& operator<<( manip3 fp ) {
          stream << fp;
          return *this;
       }
    };
    

    尤其是,ENDL的签名(可能是您唯一需要的签名)是:

    template <typename Char, typename Traits>
    std::basic_ostream<Char,Traits>& 
       std::endl( std::basic_ostream<Char,Traits>& stream );
    

    所以它落在 manip1 函数类型。其他,像 性病:十六进制 属于不同的类别( manip3 在这种特殊情况下)

        2
  •  2
  •   anon    15 年前

    我只有一个超载的操作员 一个参数的方法(如void*) 然后在这个方法中决定如何 将整数类型转换为字符*

    不,你不能。一个void*不包含类型信息,所以无法计算它实际指向的类型。

        3
  •  2
  •   David Thornley    15 年前

    只有一个重载函数。它不需要 void * 因为那是没用的。如果它采用一种数据类型,它不会被重载,并且只在转换为该类型后才看到输入值。这意味着你无法控制如何转换,比如说, int .

    如果你想要不同的行为,比如 int 和A char * ,您需要以某种方式让函数知道它得到的是什么类型,并且需要传入值。这正是重载或模板函数所做的。

        4
  •  1
  •   eduffy    15 年前

    每种类型的<<运算符是否都超载?

    有没有一种方法可以通过一个通用重载函数来实现它?

    这个问题讲不通……您只需要一个函数,还是需要一个重载函数?