为什么我们需要 using 指令和 include 指令?

发布于 2024-07-10 22:39:01 字数 430 浏览 5 评论 0原文

为什么我们在 C++ 程序中需要 using namespaceinclude 指令?

例如,

#include <iostream>

using namespace std;

int main() {
 cout << "Hello world";
}

为什么仅拥有 #include 或仅拥有 using namespace std 并摆脱另一个还不够?

(我正在考虑与 Java 进行类比,其中 import java.net.* 将从 java.net 导入所有内容,您不需要执行任何其他操作。)

Why do we need both using namespace and include directives in C++ programs?

For example,

#include <iostream>

using namespace std;

int main() {
 cout << "Hello world";
}

Why is it not enough to just have #include <iostream> or just have using namespace std and get rid of the other?

(I am thinking of an analogy with Java, where import java.net.* will import everything from java.net, you don't need to do anything else.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

站稳脚跟 2024-07-17 22:39:01

using 指令和 include 预处理器指令是两个不同的东西。 include大致对应于Java的CLASSPATH环境变量,或者java虚拟机的-cp选项。

它的作用是让编译器知道类型。 例如,只需包含 就可以引用 std::string

#include <string>
#include <iostream>

int main() {
    std::cout << std::string("hello, i'm a string");
}

现在,using 指令就像 Java 中的 import 一样。 它们使名称在它们出现的范围内可见,因此您不必再完全限定它们。 与 Java 中一样,所使用的名称在可见之前必须是已知的:

#include <string> // CLASSPATH, or -cp
#include <iostream>

// without import in java you would have to type java.lang.String . 
// note it happens that java has a special rule to import java.lang.* 
// automatically. but that doesn't happen for other packages 
// (java.net for example). But for simplicity, i'm just using java.lang here.
using std::string; // import java.lang.String; 
using namespace std; // import java.lang.*;

int main() {
    cout << string("hello, i'm a string");
}

在头文件中使用 using 指令是不好的做法,因为这意味着碰巧包含它的每个其他源文件都会使用非限定名称查找来看到这些名称。 与 Java 不同,在 Java 中,您只能使名称对导入行所在的包可见,而在 C++ 中,如果它们直接或间接包含该文件,它会影响整个程序。

即使在实现文件中,在全局范围内执行此操作时也要小心。 最好尽可能在本地使用它们。 对于命名空间 std,我从不使用它。 我和许多其他人总是在名字前面写上 std:: 。 但如果你碰巧这样做了,就这样做:

#include <string>
#include <iostream>

int main() {
    using namespace std;
    cout << string("hello, i'm a string");
}

关于命名空间是什么以及为什么需要它们,请阅读 Bjarne Stroustrup 1993 年提出的提案,将它们添加到即将发布的 C++ 标准中。 写得很好:

http://www.open -std.org/jtc1/sc22/wg21/docs/papers/1993/N0262.pdf

using directives and include preprocessor directives are two different things. The include roughly corresponds to the CLASSPATH environment variable of Java, or the -cp option of the java virtual machine.

What it does is making the types known to the compiler. Just including <string> for example will make you able to refer to std::string :

#include <string>
#include <iostream>

int main() {
    std::cout << std::string("hello, i'm a string");
}

Now, using directives are like import in Java. They make names visible in the scope they appear in, so you don't have to fully qualify them anymore. Like in Java, names used must be known before they can be made visible:

#include <string> // CLASSPATH, or -cp
#include <iostream>

// without import in java you would have to type java.lang.String . 
// note it happens that java has a special rule to import java.lang.* 
// automatically. but that doesn't happen for other packages 
// (java.net for example). But for simplicity, i'm just using java.lang here.
using std::string; // import java.lang.String; 
using namespace std; // import java.lang.*;

int main() {
    cout << string("hello, i'm a string");
}

It's bad practice to use a using directive in header files, because that means every other source file that happens to include it will see those names using unqualified name lookup. Unlike in Java, where you only make names visible to the package the import line appears in, In C++ it can affect the whole program, if they include that file directly or indirectly.

Be careful when doing it at global scope even in implementation files. Better to use them as local as possible. For namespace std, i never use that. I, and many other people, just always write std:: in front of names. But if you happen to do it, do it like this:

#include <string>
#include <iostream>

int main() {
    using namespace std;
    cout << string("hello, i'm a string");
}

For what namespaces are and why you need them, please read the proposal Bjarne Stroustrup gave 1993 for adding them to the upcoming C++ Standard. It's well written:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0262.pdf

带刺的爱情 2024-07-17 22:39:01

C++ 中,概念是独立的。 这是设计使然并且很有用。

您可以包含没有命名空间会产生歧义的内容。

使用命名空间,您可以引用两个具有相同名称的不同类。 当然,在这种情况下,您不会使用 using 指令,或者如果您使用了,则必须在您想要的命名空间中指定其他内容的命名空间。

另请注意,您不需要使用 - 您可以只使用 std::cout 或您需要访问的任何内容。 您可以使用名称空间作为项目的前缀。

In C++ the concepts are separate. This is by design and useful.

You can include things that without namespaces would be ambiguous.

With namespaces you can refer to two different classes that have the same name. Of course in that case you would not use the using directive or if you did you would have to specify the namespace of the other stuff in the namespace you wanted.

Note also that you don't NEED the using - you can just used std::cout or whatever you need to access. You preface the items with the namespace.

醉酒的小男人 2024-07-17 22:39:01

在 C++ 中,#includeusing 具有不同的功能。

#include 将包含文件的文本放入源文件中(实际上翻译单元),另一方面,命名空间只是一种具有唯一名称的机制,以便不同的人可以创建“foo”对象。

这是因为 C++ 没有模块的概念。

请记住,C++ 中的命名空间是开放的,这意味着不同的文件可以定义同一命名空间的不同部分(有点像 .NET 的部分类)。

//a.h
namespace eg {
    void foo();
}

//b.h
namespace eg {
    void bar();
}

In C++ #include and using have different functions.

#include puts the text of the included file into your source file (actually translation unit), namespaces on the other hand are just a mechanism for having unique names so that different people can create a "foo" object.

This comes from C++ not having the concept of a module.

Keep in mind that namespaces in C++ are open, that means that different files can define different parts of the same namespace (sort of like .NET's partial classes).

//a.h
namespace eg {
    void foo();
}

//b.h
namespace eg {
    void bar();
}
故事↓在人 2024-07-17 22:39:01

include 定义了函数的存在。

使用使使用它们变得更容易。

iostream 中定义的 cout 实际上名为“std::cout”。

您可以通过编写来避免使用名称空间。

std::cout << "Hello World";

The include is defining the existence of the functions.

The using is making it easier to use them.

cout as defined in iostream is actually named "std::cout".

You could avoid using the namespace by writing.

std::cout << "Hello World";
七婞 2024-07-17 22:39:01

这些关键字用于不同的目的。

using 关键字使命名空间中的名称可在当前声明性区域中使用。 这主要是为了方便,这样您就不必一直使用完全限定名称。 这个页面详细解释了它。

#include 语句是一个预处理器指令,它告诉预处理器处理指定文件的内容,就好像这些内容已经出现在该指令出现的源程序中一样。 也就是说,您可以将此语句视为将包含的文件复制到当前文件中。 然后,编译器会编译整个文件,就像您将所有代码编写在一个大文件中一样。

These keywords are used for different purposes.

The using keyword makes a name from a namespace available for use in the current declarative region. Its mostly for convenience so that you do not have to use the fully qualified name all the time. This page explains it in some detail.

The #include statement is a pre processor directive and it tells the preprocessor to treat the contents of a specified file as if those contents had appeared in the source program at the point where the directive appears. That is, you can think of this statement as copying the included file into the current one. The compiler then compiles the entire file as if you wrote all the code in one big file.

仙女 2024-07-17 22:39:01

正如所指出的,C++ 和 Java 是不同的语言,并且做的事情有些不同。 此外,C++ 更像是一种“开玩笑”的语言,而 Java 更像是一种设计语言。

虽然 using namespace std; 不一定是一个坏主意,但将它用于所有命名空间将消除整个好处。 命名空间的存在是为了让你可以编写模块而不必考虑与其他模块的名称冲突,并且使用命名空间 this; using namespace that; 可能会产生歧义。

As pointed out, C++ and Java are different languages, and do somewhat different things. Further, C++ is more of a 'jest grew' language, and Java more of a designed language.

While using namespace std; isn't necessarily a bad idea, using it for all namespaces will eliminate the whole benefit. Namespaces exist so that you can write modules without regard to name clashes with other modules, and using namespace this; using namespace that; can create ambiguities.

花开半夏魅人心 2024-07-17 22:39:01

我觉得其他答案都有点没有抓住重点。 在所有 C++、Java 和 C# 中,using/import 完全是可选的。 所以这没什么不同。

然后你必须做一些其他事情来使代码在所有三个平台上都可见。

在 C++ 中,您至少必须将其包含到当前翻译单元中(对于向量、字符串等的许多实现来说已经足够好了),通常您还必须向链接器添加一些内容,尽管有些库会根据包括(例如在 Windows 上构建时增强)。

在 C# 中,您必须添加对其他程序集的引用。 这相当于包含和链接设置。

在Java中,您必须确保代码位于类路径上,例如向其中添加相关的jar。

因此,所有三个平台上都需要非常相似的东西,并且 using/import (方便)和实际链接解析(要求)之间的分离是相同的三个全部。

I think the other answers are missing the point slightly. In all of C++, Java and C#, the using/import thing is entirely optional. So that's not different.

And then you have to do something else to make code be visible anyway, in all three platforms.

In C++, you minimally have to include it into the current translation unit (good enough for many implementations of vector, string, etc.), often you have to add something to your linker as well, although some libraries do that automatically based on the include (e.g. boost when building on Windows).

And in C# you have to add a reference to the other assembly. That takes care of the equivalent of includes and link settings.

And in Java you have to ensure the code is on the classpath, e.g. adding the relevant jar to it.

So there are very closely analogous things required on all three platforms, and the separation between using/import (a convenience) and actual linkage resolution (a requirement) is the same in all three.

想挽留 2024-07-17 22:39:01

如果你想真正理解这一点,你需要了解 命名空间

使用 include 您只需包含头文件。

通过 using namespace,您声明您正在使用包含 cout 等内容的给定名称空间。 所以如果你这样做:

using namespace std;

如果你使用cout,你可以这样做

cout << "Namespaces are good Fun";

而不是:

std::cout << "Namespaces are Awesome";

请注意,如果你不#include,你将无法在声明等中既不使用 std::cout 也不使用 cout ,因为您没有包含标头。

You need to understand namespaces if you want to truly understand this.

With include you are just including the header file.

With using namespace you are declaring you are using a given namespace that contains stuff such as cout. so if you do this:

using namespace std;

to you use cout you can just do

cout << "Namespaces are good Fun";

instead of:

std::cout << "Namespaces are Awesome";

Note that if you do not #include <iostream> you won't be able to use neither std::cout nor cout in your declarations and so forth because you're not including the header.

世态炎凉 2024-07-17 22:39:01

一个衬垫(并不是说这是新东西:)):

使用 std 允许您省略 std:: 前缀,但不能使用 cout完全没有iostream

One liner (not that this is something new :)):

using std allows you to omit std:: prefix, but you cannot use cout at all without iostream.

宛菡 2024-07-17 22:39:01

甚至 Stroustrup 也认为 #include 机制有些黑客行为。 然而,它确实使单独编译变得更加容易(提供编译后的库和标头而不是所有源代码)。

问题实际上是“为什么 C++ 在已经有了 #include 机制之后还要添加命名空间?”

据我所知,关于为什么 #include 还不够的最好例子来自 Sun。 显然,Sun 开发人员在使用他们的一款产品时遇到了一些麻烦,因为他们编写了一个 mktemp() 函数,而该函数恰好与包含的 mktemp() 函数具有相同的签名来自一个文件,该文件本身是通过项目实际想要的标头包含的。

当然,这两种功能并不兼容,并且不能用其中一种来替代另一种。 另一方面,编译器和链接器在构建二进制文件时没有意识到这一点,有时 mktemp() 会调用一个函数,有时会根据不同文件的编译顺序调用另一个函数或链接。

问题源于这样一个事实:C++ 最初与 C 兼容,并且本质上是依赖于 C 的。而 C 只有一个全局命名空间。 C++ 通过命名空间解决了这个问题——在与 C 不兼容的代码中。

C# 和 Java (1) 都有命名空间机制(C# 中的 namespace,Java 中的 package),(2) 通常通过 IDE 开发,这些 IDE 处理对二进制文件的引用开发人员,并且(3)不允许独立函数(类作用域是命名空间的一部分,并减少污染全局命名空间的风险),因此他们对这个问题有不同的解决方案。 但是,对于您正在调用的方法仍然可能存在一些歧义(例如,类继承的两个接口之间的名称冲突),并且在这种情况下,所有三种语言都要求程序员明确指定它们是哪个方法实际查找,通常是通过在父类/接口名称前面添加。

Even Stroustrup refers to the #include mechanism as somewhat hackish. However it does make separate compilation much easier (ship compiled libraries and headers instead of all source code).

The question really is "why did C++ -- after it already had the #include mechanism -- add namespaces?"

The best example I know of about why #include isn't enough comes from Sun. Apparently Sun developers had some trouble with one of their products because they had written a mktemp() function that happened to have the same signature as a mktemp() function that was included through from a file that was itself included through a header the project actually wanted.

Of course the two functions were not compatible, and one could not be used as a substitute for the other. On the other hand, the compiler and linker did not realize this when building the binary, and sometimes mktemp() would call one function, and sometimes it would call another, based on the order different files were compiled or linked.

The problem stems from the fact that C++ was originally compatible with -- and essentially piggy-backed on top of -- C. And C has only a global namespace. C++ solved this problem -- in code that is not compatible with C -- through namespaces.

Both C# and Java (1) have a namespace mechanism (namespace in C#, package in Java), (2) are usually developed through IDEs that handle referring to binaries for the developer, and (3) don't allow freestanding functions (a class scope is something of a namespace, and reduces the risk of polluting the global namespace) so they have a different solution to this problem. However, it is still possible to have some ambiguity regarding which method you're calling (say, a name clash between two interfaces that a class inherits), and in that case all three languages require the programmer to clearly specify which method they're actually looking for, usually by prepending the parent class/interface name.

白鸥掠海 2024-07-17 22:39:01

在 C++ 中,include 指令将在预处理步骤中将头文件复制并粘贴到源代码中。 应该注意的是,头文件通常包含在命名空间内声明的函数和类。 例如, 标头可能类似于以下内容:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
} 

假设您需要在主函数中定义一个向量,则可以 #include 现在您的代码中包含了上面的代码:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
}
int main(){
   /*you want to use vector here*/
}

请注意,在您的代码中,向量类仍然位于 std 命名空间中。 但是,您的 main 函数位于默认的 global 命名空间中,因此仅包含标头不会使向量类在 global 命名空间中可见。 您必须使用 using 或使用 std::vector 等前缀。

In C++, the include directive will copy and paste the header file into your source code in the preprocessing step. It should be noted that a header file generally contains functions and classes declared within a namespace. For example, the <vector> header might look similar to something like this:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
} 

Supposing you need to define a vector in your main function, you do #include <vector> and you have the piece of code above in your code now:

namespace std {
    template <class T, class Allocator = allocator<T> > class vector;
    ...
}
int main(){
   /*you want to use vector here*/
}

Notice that in your code the vector class is still located in the std namespace. However, your main function is in the default global namespace, so simply including the header will not make the vector class visible in global namespace. You have to either use using or do prefixing like std::vector.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文