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

(一)

先看一个简单的程序:

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

运行结果:

1

这里的第一行,#include好理解,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里定义的。

若你用的是Mac系统的Xcode编译器,则iostream头文件中的内容如下所示:

C++ -*-
//===--------------------------- iostream ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_IOSTREAM
#define _LIBCPP_IOSTREAM
/*
    iostream synopsis
#include <ios>
#include <streambuf>
#include <istream>
#include <ostream>
namespace std {
extern istream cin;
extern ostream cout;
extern ostream cerr;
extern ostream clog;
extern wistream wcin;
extern wostream wcout;
extern wostream wcerr;
extern wostream wclog;
}  // std
*/
#include <__config>
#include <ios>
#include <streambuf>
#include <istream>
#include <ostream>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#ifndef _LIBCPP_HAS_NO_STDIN
extern _LIBCPP_FUNC_VIS istream cin;
extern _LIBCPP_FUNC_VIS wistream wcin;
#endif
#ifndef _LIBCPP_HAS_NO_STDOUT
extern _LIBCPP_FUNC_VIS ostream cout;
extern _LIBCPP_FUNC_VIS wostream wcout;
#endif
extern _LIBCPP_FUNC_VIS ostream cerr;
extern _LIBCPP_FUNC_VIS wostream wcerr;
extern _LIBCPP_FUNC_VIS ostream clog;
extern _LIBCPP_FUNC_VIS wostream wclog;
_LIBCPP_END_NAMESPACE_STD
#endif  // _LIBCPP_IOSTREAM

可以看到,CodeBlocks和Xcode关于iostream的内容,有不小的差异。但是一些关于C++的标准,还是一致的。

(三)

那么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 B; 所以打印出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

原文发布于微信公众号 - 海天一树(gh_de7b45c40e8b)

原文发表时间:2018-06-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逸鹏说道

★Kali信息收集★8.Nmap :端口扫描

突然发现,微信一次最多推送8篇 参数:(Zenmap是Nmap图形化工具,不想打指令的可以直接使用) 详细:https://nmap.org/man/zh/in...

5664
来自专栏芋道源码1024

分布式作业系统 Elastic-Job-Lite 源码分析 —— 作业事件追踪

另外,Elastic-Job-Cloud 作业事件追踪 和 Elastic-Job-Lite 基本类似,不单独开一篇文章,记录在该文章里。如果你对 Elasti...

933
来自专栏Golang语言社区

Golang:使用 httprouter 构建 API 服务器

我 10 个月前开始成为一名 Gopher,没有回头。像许多其他 gopher 一样,我很快发现简单的语言特性对于快速构建快速、可扩展的软件非常有用。当我刚开始...

82614
来自专栏Kotlin入门系列

win7基础 cmd 查看当前已经启动的服务列表

6326
来自专栏Hadoop实操

如何在CDH启用Kerberos的情况下安装及使用Sentry(二)

使用beeline连接HiveServer2,创建columnread角色并授权test表s1列的读权限,将columnread角色授权给fayson_r用户组

1.5K8
来自专栏CDN及云技术分享

Openssl状态机的实现

Openssl是通过“握手“建立加密信道,在该信道双方的身份都是合法的,并且传输数据都是密文传输。Openssl握手通过客户端和服务端互相交换信息计算出secr...

4263
来自专栏吴伟祥

Linux命令缩写英文对照记忆(〇) 转

1292
来自专栏Seebug漏洞平台

花式窃取NetNTLM哈希的方法

原文:https://osandamalith.com/2017/03/24/places-of-interest-in-stealing-netntlm-ha...

3308
来自专栏FreeBuf

Scrounger:一款功能强大的移动端应用程序安全测试套件

今天给大家介绍的是一款名叫Scrounger 的工具,广大研究人员可以使用这款工具来对移动端应用程序的安全性进行测试。首先,这款工具参考和借鉴了很多目前安全社区...

1301
来自专栏蓝天

同时具备多线程和多进程安全的写日志工具

接口请浏览:https://github.com/eyjian/mooon/blob/master/mooon/include/mooon/sys/log.h ...

2614

扫码关注云+社区

领取腾讯云代金券