3

过去到 ostream 对象的任何系统定义的用户类型都被转换为字符串或 char* 吗?

像 cout<<4<<"Hello World";

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

如果我使用模板重载运算符 << ,事情就会部分起作用,即

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

4 回答 4

11

重新阅读您的问题后(​​由于此答案中的评论),我意识到您想要的不仅是转换为字符串(我在此处的另一个答案中的假设),而是转发到内部 ofstream。

现在,您想要实现的目标并不简单,而且在大多数情况下可能是矫枉过正。在[make_string][3]我拥有的实现中(转发到 internal ostringstream),我不允许传递操纵器。如果用户想要添加一个新行(我们在 linux 下开发),他们只需传递一个 '\n' 字符。

您的问题是转发操纵器(std::hexstd::endl...)。您的 operator<< 被定义为采用 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函数的类型。其他,例如std::hex属于不同的类别(manip3在这种特殊情况下)

于 2009-07-15T22:34:22.703 回答
2

我只有一个带有一个参数的重载运算符方法(如 void*),然后在该方法内部决定如何将整数类型转换为 char*

不,你不能。void * 不携带类型信息,因此无法确定它实际指向的类型。

于 2009-07-15T20:29:42.080 回答
2

只有一个重载函数。它不需要 a void *,因为那将毫无用处。如果它采用一种数据类型,则不会重载,并且仅在将输入值转换为该类型后才能看到输入值。这意味着您无法控制如何转换,例如,一个int.

int如果你想要在 an和 a之间有不同的行为char *,你需要让函数以某种方式知道它正在获取什么类型,并且你需要传递值。这正是重载或模板函数所做的。

于 2009-07-15T20:33:46.503 回答
1

<< 运算符是否为每种类型重载?

是的

有没有办法通过一个通用的重载函数来实现它?

这个问题没有意义..您只想要一个函数,还是想要一个重载函数?

于 2009-07-15T20:20:09.353 回答