首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

关于namespace和directive的有关问题

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

关于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 指令只有一个功能,把(名空间中的)名字导入作用域。



热点排行