神刀安全网

小朋友学C++(21):命名空间

先看一个简单的程序:

#include <iostream> using namespace std;  int main() {     int a = 1;     cout << a << endl; } 

运行结果:

1 

这里的第一行,#include<iostream>好理解,iostream是输入输出流,包含了输入流istream和输出流ostream。
第二行using namespace std;
这里的namespace是个关键字,表示它后面的std是一个命名空间。

什么是命名空间呢?
假定三年1班有一名小学生叫做寒上耕,三年2班也有一名小学生叫做寒上耕,四年3班也有一名小学生叫寒上耕,假如有个人说:我要找寒上耕。那么没人知道他要找哪位寒上耕。但是假如有个人说:我要找三年1班的寒上耕,大家就知道他要找的是认谁。
这里的三年1班,三年2班,四年3班,就是命名空间,作用是防止命名冲突。

那么程序里为何要使用命名空间std呢?不用行不行?
若把using namespace std;这行代码去掉,cout和endl会报错,程序不认识这两个词。

咱们看一个iostream中的代码(我用的编译器是CodeBlocks):

#ifndef _GLIBCXX_IOSTREAM #define _GLIBCXX_IOSTREAM 1  #pragma GCC system_header  #include <bits/c++config.h> #include <ostream> #include <istream>  namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION    /**    *  @name Standard Stream Objects    *    *  The &lt;iostream&gt; header declares the eight <em>standard stream    *  objects</em>.  For other declarations, see    *  http://gcc.gnu.org/onlinedocs/libstdc++/manual/io.html    *  and the @link iosfwd I/O forward declarations @endlink    *    *  They are required by default to cooperate with the global C    *  library's @c FILE streams, and to be available during program    *  startup and termination. For more information, see the section of the    *  manual linked to above.   */   //@{   extern istream cin;       /// Linked to standard input   extern ostream cout;      /// Linked to standard output   extern ostream cerr;      /// Linked to standard error (unbuffered)   extern ostream clog;      /// Linked to standard error (buffered)  #ifdef _GLIBCXX_USE_WCHAR_T   extern wistream wcin;     /// Linked to standard input   extern wostream wcout;    /// Linked to standard output   extern wostream wcerr;    /// Linked to standard error (unbuffered)   extern wostream wclog;    /// Linked to standard error (buffered) #endif   //@}    // For construction of filebuffers for cout, cin, cerr, clog et. al.   static ios_base::Init __ioinit;  _GLIBCXX_END_NAMESPACE_VERSION } // namespace  #endif /* _GLIBCXX_IOSTREAM */ 

咱们看到了在iosteam中,cin(输入),cout(输出),cerr(错误),clog(日志)都是在std里定义的。

那么endl是在哪里定义的呢?
咱们看一下定义endl的源码,具体是定义在ostream里面

#ifndef _GLIBCXX_OSTREAM #define _GLIBCXX_OSTREAM 1  #pragma GCC system_header  #include <ios> #include <bits/ostream_insert.h>  namespace std _GLIBCXX_VISIBILITY(default) {   ......   ...... _GLIBCXX_BEGIN_NAMESPACE_VERSION   template<typename _CharT, typename _Traits>     inline basic_ostream<_CharT, _Traits>&     endl(basic_ostream<_CharT, _Traits>& __os)     { return flush(__os.put(__os.widen('/n'))); }   ......   ...... _GLIBCXX_END_NAMESPACE_VERSION } // namespace std  #include <bits/ostream.tcc>  #endif  /* _GLIBCXX_OSTREAM */ 

可以看到,endl是定义在ostream中的std中。
因为iostream头文件已经包含了ostream头文件和istream头文件,所以咱们的代码中只需要包含iostream头文件即可。

另一方面,咱们注意到,在iostream头文件和ostream头文件中都包含了命名空间std。可见命名空间可以散布到不同的头文件。事实上,std不止在这两个头文件中有,在其他的头文件中也有,作用是把一些常用的操作符都包含进来。然后在你写的代码中引入using namespace std;后,即可减少命名冲突。

假如咱们不写using namepace std;那么在使用相关的操作符时,需要加上std

#include <iostream>  int main() {     int a = 1;     std::cout << a << std::endl; } 

再看一个例子

#include <iostream>  namespace A {     int x = 10; };  namespace B {     int x = 20; };  using namespace B;  int main() {     std::cout << x << std::endl; } 

这个程序里,有两个命名空间A和B,都定义了变量x。因为已经说明了using namespace std; 所以打印出20。
若没说明使用哪个命名空间,必须在x前面指明命名空间,否则编译会报错。

#include <iostream>  namespace A {     int x = 10; };  namespace B {     int x = 20; };  int main() {     std::cout << B::x << std::endl;     std::cout << A::x << std::endl; } 

运行结果:

20 10 

TopCoder & Codeforces & AtCoder交流QQ群:648202993
更多内容请关注微信公众号

小朋友学C++(21):命名空间

wechat_public_header.jpg

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » 小朋友学C++(21):命名空间

分享到:更多 ()