读书人

关于namespace和directive的有关问题

发布时间: 2013-12-10 15:05:55 作者: rapoo

关于namespace和directive的问题
一直不清楚namespace和directive之间的区别——我指的是实质而非形式上的区别。

比如说,几乎所有的C++程序都会使用#include<iostream>,但是既然这样的话,为什么我们还需要
额外使用
using namespace std;
或者类似std::cin这样的东西?毕竟,我们知道cin这些东西是在iostream里定义的。不过我好像想通了:在同一个程序中可能有这样的两个独立的部分:


{
std::cin>>num;
}




{
my_own::cin>>num;
}

其中my_own是程序员自己定义的一个包含了cin的namespace,这就可以理解为什么需要namespace这种东西了。

但是,我还有一个疑问:假如my_own::cin是定义在users.h这个头文件中的,那么上面的两部分程序从效果上(从语法上当然是不合法的)看与下面的有什么区别?

{
#include<iostream>
cin>>num;
}




{
#include "users.h"
my_own::cin>>num;
}


换句话说,为什么C++不允许在同一个源文件中多次出现同一个#include语句?如果允许的话,不就可以免去namespace的问题了吗?
[解决办法]
#include是一个预处理命令,和#define的效果是一样的,就是替换出现的内容。include的作用是把包括的文件的具体内容,全部包括进该编译文件。C/C++的每一个编译文件(.c、.cpp之类的文件)都是分开编译的,最后再做连接,所以需要把头文件代码引入到相应的.c、.cpp之类的文件中。

一般为了防止重复声明(不是重复定义)都加了#ifndef这种命令,防止重复引入。所以每个头文件只引入一次,如果要像namespace这种,在不同的函数中选择性使用using namespace是不行的,如果你这样做,那#include出现的头文件(加防重声明保护)只会出现在第一个地方。

using和#include各司其职,互不冲突。
[解决办法]
C,C++ 按照需要,编译链接程序。
而不是把定义的在标准库的代码,都全部编译到程序中,从而所有名字可见。

#include 把文件中的一些定义,声明 导入.c,.cpp ,这些名字就具有可见性了。
C++
使用 using ,不过是

使得“引用的时候,可以省略作用域名字,和作用域限定符::”,
从而使得代码,更简练一点而已。

不用 using,该名字同样可见,不过用法比较臃肿,需要加域名和作用域限定符而已。

换句话说,C++不用using,只用#include ,就像 C 那样了,
头文件中的一切,.cpp 已经可以用了。

用了 using 就相当于该名字;
或者该名空间所有的名字,
不是在名空间定义的那么样,可以直接使用,不需要那么嗦了。




[解决办法]
using
假设我们把名空间,看作姓氏。

通常我们叫一个人的名字,是姓名一起叫。

熟悉以后,或者一起长大的人们,就会忽略姓氏,只叫名字。
C++
某段代码,要引用标准库,则该代码没有和标准库的代码之间,我们比较熟,或者我们一起长大的说法,

他用using告诉我们。
这个名字,或者这个姓氏的所有名字,只要直呼其名,就行,姓氏就可以忽略了。

using指令,就是这点作用。
不用他,只用#include ,代码照跑。





[解决办法]
#include <iostream>

namespace a
{
int g = 0;
}

namespace b
{
int g = 1;
}

int main()
{
std::cout << a::g << " " << b::g << std::endl;
}

[解决办法]
#include 是根本。
using指令,只起到简化代码的作用。

[解决办法]
引用:
Quote: 引用:


其实我最想知道的是:既然已经用了using了,为什么还要#include?前者不是比后者更加具体吗?


using 只是告诉编译器,该名字,或者名空间中的所有名字;
可以不用加域名和作用域限定符了。

但是 这个名字,实在某个文件中定义的,需要声明一下(比如外部变量,函数),或者定义一下(比如数据类型);
才可以使用,这个声明或者定义,不能通过 using 指令实现。
要么直接写出来,要么
#include 头文件达到,
这个声明或者定义,已经写在这个实现文件(.cpp,.cc,.cxx)中了的目的。

而且 名空间里,定义了哪些名字,是通过#include头文件,才知道的。

如果,没有#include头文件,编译器,

除非发现,该实现文件,也在本文件的某个地方,定义了同一名空间;
并在该名空间,定义这(个)些名字(外部变量,函数,数据类型,常量等)

否则并不认为,名空间里面已经定义了某个名字(外部变量,函数,数据类型,常量等)
只有通过#include指令,把头文件并入实现文件;
在名空间内定义了那些名字,才被编译器认可。

就是说,
namespace space {
int foo();
.....
};

这种代码,直接或者通过#include 间接出现在,实现文件中。
编译器,才认为
某个namespace
这个例子是 space,里面定义了某个名字, 例如foo这个函数。

PS :
C,C++ 标准库的代码;
不是必然可以使用的;
至少要通过#include头文件,才可以使用.

之所以C++ 标准库,需要 #include 和using指令一起用;
是因为

#include 用于使得库代码,包括其中的名空间,可用。

using 使得 #include 的代码中,名空间内部的名字;
出现在当前作用域。
可以直接使用,不用附加域名和限定符。

由于 早期的C++ 标准库,
#include 就可以使用,没有名空间的概念。

后来的标准
C++有了名空间,就规定,C++标准库,省略.h
C++标准库的代码,都定义在std 名空间内部。
为了兼容以前的标准,
以便编译老标准的文件,改动最小,引入了using 指令。

这样

原来老标准下的
#include <iostream.h>
只要改成
#include <iostream>
using namespace std;
在新标准下,就可以了。
其他代码就不用改动了。

using std::cin 只是顺便增加的功能。
这样使得不同名空间下,可以定义重复的名字,

只要本作用域,不using 整个名空间
除了明确 using 的那个名字外,
其他名字都可以和名空间内部的名字重名。

从而最大限度的,避免了名字冲突。











[解决办法]
using 指令只有一个功能,把(名空间中的)名字导入作用域。



读书人网 >C++

热点推荐