我那本C++ 的教材都看得八八九九了,于是想了解很多对象的原始定义, 例如cout。 于是我查找了ostream.h 这个文件。
简直是头晕, 都不知道写了什么。查到关于cout的下面这句
extern ostream_withassign _CRTIMP cout;书上说cout对象是ostream 类的派生类的对象。 我想很`详细了解ostream 类, 请问应该怎样做?
简直是头晕, 都不知道写了什么。查到关于cout的下面这句
extern ostream_withassign _CRTIMP cout;书上说cout对象是ostream 类的派生类的对象。 我想很`详细了解ostream 类, 请问应该怎样做?
在 MFC 里好像没有这个类呀~
C++书上的关于io 流这个章节有说的
核心是个IOS,
然后是ISTREAM,然后OSTREAM,
最后虚拟继承IOSTREAM。
你打开iostream这个文件,看看包含的哪个文件。然后再看看吧。
老版本可能只有头文件,新版本是基于模板的。
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 }
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
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
http://gcc.gnu.org/onlinedocs/
不过我觉得你的学习精神还是很值得钦佩的!
class basic_ostream : virtual public basic_ios<_CharT, _Traits>这个就是OSTREAM原代码,
虚拟继承的典范。
COUT在MFC里面没用不是因为其他原因而是因为MFC大部分都是窗口类。
事实上假如写个控制台程序用MFC中的像什么CSTRING之类的也是可以的。这样也还可以用COUTIOSTREAM的代码也是个经典,特别是想写自己的缓冲区处理的人最好来看一看。
模板类的看不懂就去找一下老的代码吧。
老的直接是字符指针的。