我那本C++ 的教材都看得八八九九了,于是想了解很多对象的原始定义, 例如cout。 于是我查找了ostream.h 这个文件。 
简直是头晕, 都不知道写了什么。查到关于cout的下面这句
extern ostream_withassign _CRTIMP cout;书上说cout对象是ostream 类的派生类的对象。 我想很`详细了解ostream 类, 请问应该怎样做?

解决方案 »

  1.   


    在 MFC 里好像没有这个类呀~
      

  2.   

    不一定要MFC里面有这个类, 程序才能运行吧。
    C++书上的关于io 流这个章节有说的
      

  3.   

    这个是有原代码的
    核心是个IOS,
    然后是ISTREAM,然后OSTREAM,
    最后虚拟继承IOSTREAM。
    你打开iostream这个文件,看看包含的哪个文件。然后再看看吧。
    老版本可能只有头文件,新版本是基于模板的。
      

  4.   

    00043 #pragma GCC system_header
    00044 
    00045 #include <ios>
    00046 
    00047 namespace std
    00048 {
    00049   // [27.6.2.1] Template class basic_ostream
    00050   /**
    00051    *  @brief  Controlling output.
    00052    *
    00053    *  This is the base class for all output streams.  It provides text
    00054    *  formatting of all builtin types, and communicates with any class
    00055    *  derived from basic_streambuf to do the actual output.
    00056   */
    00057   template<typename _CharT, typename _Traits>
    00058     class basic_ostream : virtual public basic_ios<_CharT, _Traits>
    00059     {
    00060     public:
    00061       // Types (inherited from basic_ios (27.4.4)):
    00062       typedef _CharT                            char_type;
    00063       typedef typename _Traits::int_type        int_type;
    00064       typedef typename _Traits::pos_type        pos_type;
    00065       typedef typename _Traits::off_type        off_type;
    00066       typedef _Traits                           traits_type;
    00067       
    00068       // Non-standard Types:
    00069       typedef basic_streambuf<_CharT, _Traits>      __streambuf_type;
    00070       typedef basic_ios<_CharT, _Traits>        __ios_type;
    00071       typedef basic_ostream<_CharT, _Traits>        __ostream_type;
    00072       typedef ostreambuf_iterator<_CharT, _Traits>  __ostreambuf_iter;
    00073       typedef num_put<_CharT, __ostreambuf_iter>        __numput_type;
    00074       typedef ctype<_CharT>                     __ctype_type;
    00075 
    00076       template<typename _CharT2, typename _Traits2>
    00077         friend basic_ostream<_CharT2, _Traits2>&
    00078         operator<<(basic_ostream<_CharT2, _Traits2>&, _CharT2);
    00079  
    00080       template<typename _Traits2>
    00081         friend basic_ostream<char, _Traits2>&
    00082         operator<<(basic_ostream<char, _Traits2>&, char);
    00083  
    00084       template<typename _CharT2, typename _Traits2>
    00085         friend basic_ostream<_CharT2, _Traits2>&
    00086         operator<<(basic_ostream<_CharT2, _Traits2>&, const _CharT2*);
    00087  
    00088       template<typename _Traits2>
    00089         friend basic_ostream<char, _Traits2>&
    00090         operator<<(basic_ostream<char, _Traits2>&, const char*);
    00091  
    00092       template<typename _CharT2, typename _Traits2>
    00093         friend basic_ostream<_CharT2, _Traits2>&
    00094         operator<<(basic_ostream<_CharT2, _Traits2>&, const char*);
    00095 
    00096       // [27.6.2.2] constructor/destructor
    00097       /**
    00098        *  @brief  Base constructor.
    00099        *
    00100        *  This ctor is almost never called by the user directly, rather from
    00101        *  derived classes' initialization lists, which pass a pointer to
    00102        *  their own stream buffer.
    00103       */
    00104       explicit 
    00105       basic_ostream(__streambuf_type* __sb)
    00106       { this->init(__sb); }
    00107 
    00108       /**
    00109        *  @brief  Base destructor.
    00110        *
    00111        *  This does very little apart from providing a virtual base dtor.
    00112       */
    00113       virtual 
    00114       ~basic_ostream() { }
    00115 
    00116       // [27.6.2.3] prefix/suffix
    00117       class sentry;
    00118       friend class sentry;
    00119       
    00120       // [27.6.2.5] formatted output
    00121       // [27.6.2.5.3]  basic_ostream::operator<<
    00122       //@{
    00123       /**
    00124        *  @brief  Interface for manipulators.
    00125        *
    00126        *  Manuipulators such as @c std::endl and @c std::hex use these
    00127        *  functions in constructs like "std::cout << std::endl".  For more
    00128        *  information, see the iomanip header.
    00129       */
    00130       __ostream_type&
    00131       operator<<(__ostream_type& (*__pf)(__ostream_type&));
    00132       
    00133       __ostream_type&
    00134       operator<<(__ios_type& (*__pf)(__ios_type&));
    00135       
    00136       __ostream_type&
    00137       operator<<(ios_base& (*__pf) (ios_base&));
    00138       //@}
    00139 
    00140       // [27.6.2.5.2] arithmetic inserters
    00141       /**
    00142        *  @name Arithmetic Inserters
    00143        *
    00144        *  All the @c operator<< functions (aka <em>formatted output
    00145        *  functions</em>) have some common behavior.  Each starts by
    00146        *  constructing a temporary object of type std::basic_ostream::sentry.
    00147        *  This can have several effects, concluding with the setting of a
    00148        *  status flag; see the sentry documentation for more.
    00149        *
    00150        *  If the sentry status is good, the function tries to generate
    00151        *  whatever data is appropriate for the type of the argument.
    00152        *
    00153        *  If an exception is thrown during insertion, ios_base::badbit
    00154        *  will be turned on in the stream's error state without causing an
    00155        *  ios_base::failure to be thrown.  The original exception will then
    00156        *  be rethrown.
    00157       */
    00158       //@{
    00159       /**
    00160        *  @brief  Basic arithmetic inserters
    00161        *  @param  A variable of builtin type.
    00162        *  @return  @c *this if successful
    00163        *
    00164        *  These functions use the stream's current locale (specifically, the
    00165        *  @c num_get facet) to perform numeric formatting.
    00166       */
    00167       __ostream_type& 
    00168       operator<<(long __n);
    00169       
    00170       __ostream_type& 
    00171       operator<<(unsigned long __n);
    00172 
    00173       __ostream_type& 
    00174       operator<<(bool __n);
    00175 
    00176       __ostream_type& 
    00177       operator<<(short __n)
    00178       { 
    00179     ios_base::fmtflags __fmt = this->flags() & ios_base::basefield;
    00180     if (__fmt & ios_base::oct || __fmt & ios_base::hex)
    00181       return this->operator<<(static_cast<unsigned long>
    00182                   (static_cast<unsigned short>(__n)));
    00183     else
    00184       return this->operator<<(static_cast<long>(__n));
    00185       }
    00186 
    00187       __ostream_type& 
    00188       operator<<(unsigned short __n)
    00189       { return this->operator<<(static_cast<unsigned long>(__n)); }
    00190 
    00191       __ostream_type& 
    00192       operator<<(int __n)
    00193       { 
    00194     ios_base::fmtflags __fmt = this->flags() & ios_base::basefield;
    00195     if (__fmt & ios_base::oct || __fmt & ios_base::hex)
    00196       return this->operator<<(static_cast<unsigned long>
    00197                   (static_cast<unsigned int>(__n)));
    00198     else
    00199       return this->operator<<(static_cast<long>(__n));
    00200       }
      

  5.   

    00202       __ostream_type& 
    00203       operator<<(unsigned int __n)
    00204       { return this->operator<<(static_cast<unsigned long>(__n)); }
    00205 
    00206 #ifdef _GLIBCXX_USE_LONG_LONG
    00207       __ostream_type& 
    00208       operator<<(long long __n);
    00209 
    00210       __ostream_type& 
    00211       operator<<(unsigned long long __n);
    00212 #endif
    00213 
    00214       __ostream_type& 
    00215       operator<<(double __f);
    00216 
    00217       __ostream_type& 
    00218       operator<<(float __f)
    00219       { return this->operator<<(static_cast<double>(__f)); }
    00220 
    00221       __ostream_type& 
    00222       operator<<(long double __f);
    00223 
    00224       __ostream_type& 
    00225       operator<<(const void* __p);
    00226 
    00227       /**
    00228        *  @brief  Extracting from another streambuf.
    00229        *  @param  sb  A pointer to a streambuf
    00230        *
    00231        *  This function behaves like one of the basic arithmetic extractors,
    00232        *  in that it also constructs a sentry object and has the same error
    00233        *  handling behavior.
    00234        *
    00235        *  If @a sb is NULL, the stream will set failbit in its error state.
    00236        *
    00237        *  Characters are extracted from @a sb and inserted into @c *this
    00238        *  until one of the following occurs:
    00239        *
    00240        *  - the input stream reaches end-of-file,
    00241        *  - insertion into the output sequence fails (in this case, the
    00242        *    character that would have been inserted is not extracted), or
    00243        *  - an exception occurs while getting a character from @a sb, which
    00244        *    sets failbit in the error state
    00245        *
    00246        *  If the function inserts no characters, failbit is set.
    00247       */
    00248       __ostream_type& 
    00249       operator<<(__streambuf_type* __sb);
    00250       //@}
    00251 
    00252       // [27.6.2.6] unformatted output functions
    00253       /**
    00254        *  @name Unformatted Output Functions
    00255        *
    00256        *  All the unformatted output functions have some common behavior.
    00257        *  Each starts by constructing a temporary object of type
    00258        *  std::basic_ostream::sentry.  This has several effects, concluding
    00259        *  with the setting of a status flag; see the sentry documentation
    00260        *  for more.
    00261        *
    00262        *  If the sentry status is good, the function tries to generate
    00263        *  whatever data is appropriate for the type of the argument.
    00264        *
    00265        *  If an exception is thrown during insertion, ios_base::badbit
    00266        *  will be turned on in the stream's error state.  If badbit is on in
    00267        *  the stream's exceptions mask, the exception will be rethrown
    00268        *  without completing its actions.
    00269       */
    00270       //@{
    00271       /**
    00272        *  @brief  Simple insertion.
    00273        *  @param  c  The character to insert.
    00274        *  @return  *this
    00275        *
    00276        *  Tries to insert @a c.
    00277        *
    00278        *  @note  This function is not overloaded on signed char and
    00279        *         unsigned char.
    00280       */
    00281       __ostream_type& 
    00282       put(char_type __c);
    00283 
    00284       // Core write functionality, without sentry.
    00285       void
    00286       _M_write(const char_type* __s, streamsize __n)
    00287       {
    00288     streamsize __put = this->rdbuf()->sputn(__s, __n);
    00289     if (__put != __n)
    00290       this->setstate(ios_base::badbit);
    00291       }
    00292 
    00293       /**
    00294        *  @brief  Character string insertion.
    00295        *  @param  s  The array to insert.
    00296        *  @param  n  Maximum number of characters to insert.
    00297        *  @return  *this
    00298        *
    00299        *  Characters are copied from @a s and inserted into the stream until
    00300        *  one of the following happens:
    00301        *
    00302        *  - @a n characters are inserted
    00303        *  - inserting into the output sequence fails (in this case, badbit
    00304        *    will be set in the stream's error state)
    00305        *
    00306        *  @note  This function is not overloaded on signed char and
    00307        *         unsigned char.
    00308       */
    00309       __ostream_type& 
    00310       write(const char_type* __s, streamsize __n);
    00311       //@}
    00312 
    00313       /**
    00314        *  @brief  Synchronizing the stream buffer.
    00315        *  @return  *this
    00316        *
    00317        *  If @c rdbuf() is a null pointer, changes nothing.
    00318        *
    00319        *  Otherwise, calls @c rdbuf()->pubsync(), and if that returns -1,
    00320        *  sets badbit.
    00321       */
    00322       __ostream_type& 
    00323       flush();
    00324 
    00325       // [27.6.2.4] seek members
    00326       /**
    00327        *  @brief  Getting the current write position.
    00328        *  @return  A file position object.
    00329        *
    00330        *  If @c fail() is not false, returns @c pos_type(-1) to indicate
    00331        *  failure.  Otherwise returns @c rdbuf()->pubseekoff(0,cur,out).
    00332       */
    00333       pos_type 
    00334       tellp();
    00335 
    00336       /**
    00337        *  @brief  Changing the current write position.
    00338        *  @param  pos  A file position object.
    00339        *  @return  *this
    00340        *
    00341        *  If @c fail() is not true, calls @c rdbuf()->pubseekpos(pos).  If
    00342        *  that function fails, sets failbit.
    00343       */
    00344       __ostream_type& 
    00345       seekp(pos_type);
    00346 
    00347       /**
    00348        *  @brief  Changing the current write position.
    00349        *  @param  off  A file offset object.
    00350        *  @param  dir  The direction in which to seek.
    00351        *  @return  *this
    00352        *
    00353        *  If @c fail() is not true, calls @c rdbuf()->pubseekoff(off,dir).
    00354        *  If that function fails, sets failbit.
    00355       */
    00356        __ostream_type& 
    00357       seekp(off_type, ios_base::seekdir);
    00358       
    00359     protected:
    00360       explicit 
    00361       basic_ostream() { }
    00362     };
    00363 
    00364   /**
    00365    *  @brief  Performs setup work for output streams.
    00366    *
    00367    *  Objects of this class are created before all of the standard
    00368    *  inserters are run.  It is responsible for "exception-safe prefix and
    00369    *  suffix operations."  Additional actions may be added by the
    00370    *  implementation, and we list them in
    00371    *  http://gcc.gnu.org/onlinedocs/libstdc++/17_intro/howto.html#5
    00372    *  under [27.6] notes.
    00373   */
    00374   template <typename _CharT, typename _Traits>
    00375     class basic_ostream<_CharT, _Traits>::sentry
    00376     {
    00377       // Data Members:
    00378       bool              _M_ok;
    00379       basic_ostream<_CharT,_Traits>&    _M_os;
    00380       
    00381     public:
    00382       /**
    00383        *  @brief  The constructor performs preparatory work.
    00384        *  @param  os  The output stream to guard.
    00385        *
    00386        *  If the stream state is good (@a os.good() is true), then if the
    00387        *  stream is tied to another output stream, @c is.tie()->flush()
    00388        *  is called to synchronize the output sequences.
    00389        *
    00390        *  If the stream state is still good, then the sentry state becomes
    00391        *  true ("okay").
    00392       */
    00393       explicit
    00394       sentry(basic_ostream<_CharT,_Traits>& __os);
    00395 
    00396       /**
    00397        *  @brief  Possibly flushes the stream.
    00398        *
    00399        *  If @c ios_base::unitbuf is set in @c os.flags(), and
    00400        *  @c std::uncaught_exception() is true, the sentry destructor calls
      

  6.   

    // XXX MT
    00406     if (_M_os.flags() & ios_base::unitbuf && !uncaught_exception())
    00407       {
    00408         // Can't call flush directly or else will get into recursive lock.
    00409         if (_M_os.rdbuf() && _M_os.rdbuf()->pubsync() == -1)
    00410           _M_os.setstate(ios_base::badbit);
    00411       }
    00412       }
    00413 
    00414       /**
    00415        *  @brief  Quick status checking.
    00416        *  @return  The sentry state.
    00417        *
    00418        *  For ease of use, sentries may be converted to booleans.  The
    00419        *  return value is that of the sentry state (true == okay).
    00420       */
    00421       operator bool() const
    00422       { return _M_ok; }
    00423     };
    00424 
    00425   // [27.6.2.5.4] character insertion templates
    00426   //@{
    00427   /**
    00428    *  @brief  Character inserters
    00429    *  @param  out  An output stream.
    00430    *  @param  c  A character.
    00431    *  @return  out
    00432    *
    00433    *  Behaves like one of the formatted arithmetic inserters described in
    00434    *  std::basic_ostream.  After constructing a sentry object with good
    00435    *  status, this function inserts a single character and any required
    00436    *  padding (as determined by [22.2.2.2.2]).  @c out.width(0) is then
    00437    *  called.
    00438    *
    00439    *  If @a c is of type @c char and the character type of the stream is not
    00440    *  @c char, the character is widened before insertion.
    00441   */
    00442   template<typename _CharT, typename _Traits>
    00443     basic_ostream<_CharT, _Traits>&
    00444     operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c);
    00445 
    00446   template<typename _CharT, typename _Traits>
    00447     basic_ostream<_CharT, _Traits>&
    00448     operator<<(basic_ostream<_CharT, _Traits>& __out, char __c)
    00449     { return (__out << __out.widen(__c)); }
    00450 
    00451   // Specialization
    00452   template <class _Traits> 
    00453     basic_ostream<char, _Traits>&
    00454     operator<<(basic_ostream<char, _Traits>& __out, char __c);
    00455 
    00456   // Signed and unsigned
    00457   template<class _Traits>
    00458     basic_ostream<char, _Traits>&
    00459     operator<<(basic_ostream<char, _Traits>& __out, signed char __c)
    00460     { return (__out << static_cast<char>(__c)); }
    00461   
    00462   template<class _Traits>
    00463     basic_ostream<char, _Traits>&
    00464     operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c)
    00465     { return (__out << static_cast<char>(__c)); }
    00466   //@}
    00467   
    00468   //@{
    00469   /**
    00470    *  @brief  String inserters
    00471    *  @param  out  An output stream.
    00472    *  @param  s  A character string.
    00473    *  @return  out
    00474    *  @pre  @a s must be a non-NULL pointer
    00475    *
    00476    *  Behaves like one of the formatted arithmetic inserters described in
    00477    *  std::basic_ostream.  After constructing a sentry object with good
    00478    *  status, this function inserts @c traits::length(s) characters starting
    00479    *  at @a s, widened if necessary, followed by any required padding (as
    00480    *  determined by [22.2.2.2.2]).  @c out.width(0) is then called.
    00481   */
    00482   template<typename _CharT, typename _Traits>
    00483     basic_ostream<_CharT, _Traits>&
    00484     operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s);
    00485 
    00486   template<typename _CharT, typename _Traits>
    00487     basic_ostream<_CharT, _Traits> &
    00488     operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s);
    00489 
    00490   // Partial specializationss
    00491   template<class _Traits>
    00492     basic_ostream<char, _Traits>&
    00493     operator<<(basic_ostream<char, _Traits>& __out, const char* __s);
    00494  
    00495   // Signed and unsigned
    00496   template<class _Traits>
    00497     basic_ostream<char, _Traits>&
    00498     operator<<(basic_ostream<char, _Traits>& __out, const signed char* __s)
    00499     { return (__out << reinterpret_cast<const char*>(__s)); }
    00500 
    00501   template<class _Traits>
    00502     basic_ostream<char, _Traits> &
    00503     operator<<(basic_ostream<char, _Traits>& __out, const unsigned char* __s)
    00504     { return (__out << reinterpret_cast<const char*>(__s)); }
    00505   //@}
    00506 
    00507   // [27.6.2.7] standard basic_ostream manipulators
    00508   /**
    00509    *  @brief  Write a newline and flush the stream.
    00510    *
    00511    *  This manipulator is often mistakenly used when a simple newline is
    00512    *  desired, leading to poor buffering performance.  See
    00513    *  http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#2 for more
    00514    *  on this subject.
    00515   */
    00516   template<typename _CharT, typename _Traits>
    00517     basic_ostream<_CharT, _Traits>& 
    00518     endl(basic_ostream<_CharT, _Traits>& __os)
    00519     { return flush(__os.put(__os.widen('\n'))); }
    00520 
    00521   /**
    00522    *  @brief  Write a null character into the output sequence.
    00523    *
    00524    *  "Null character" is @c CharT() by definition.  For CharT of @c char,
    00525    *  this correctly writes the ASCII @c NUL character string terminator.
    00526   */
    00527   template<typename _CharT, typename _Traits>
    00528     basic_ostream<_CharT, _Traits>& 
    00529     ends(basic_ostream<_CharT, _Traits>& __os)
    00530     { return __os.put(_CharT()); }
    00531   
    00532   /**
    00533    *  @brief  Flushes the output stream.
    00534    *
    00535    *  This manipulator simply calls the stream's @c flush() member function.
    00536   */
    00537   template<typename _CharT, typename _Traits>
    00538     basic_ostream<_CharT, _Traits>& 
    00539     flush(basic_ostream<_CharT, _Traits>& __os)
    00540     { return __os.flush(); }
    00541 
    00542 } // namespace std
      

  7.   

    网上也有原代码
    http://gcc.gnu.org/onlinedocs/
      

  8.   

    cout在MFC里面没用的。
    不过我觉得你的学习精神还是很值得钦佩的!
      

  9.   

    template<typename _CharT, typename _Traits>
    class basic_ostream : virtual public basic_ios<_CharT, _Traits>这个就是OSTREAM原代码,
    虚拟继承的典范。
    COUT在MFC里面没用不是因为其他原因而是因为MFC大部分都是窗口类。
    事实上假如写个控制台程序用MFC中的像什么CSTRING之类的也是可以的。这样也还可以用COUTIOSTREAM的代码也是个经典,特别是想写自己的缓冲区处理的人最好来看一看。
    模板类的看不懂就去找一下老的代码吧。
    老的直接是字符指针的。