简体   繁体   English

C ++转换单元

[英]C++ Translation Unit

I didn't really understand what a translation unit is and how to use unnamed namespaces: 我不太了解翻译单元是什么以及如何使用未命名的命名空间:

If I have a .cpp file: 如果我有一个.cpp文件:

namespace
{
    void extFunction()
    {
        std::cout << "Called Unnamed Namespace's function.\n";
    }
}

and a main .cpp file: 和一个主要的.cpp文件:

#include <iostream>
#include "ext.cpp"

using namespace std;

int main()
{
    extFunction();


    return 0;
}

Why can I access a member of an Unnamed Namespace from another file? 为什么我可以从另一个文件访问未命名命名空间的成员?

EDIT: 编辑:

Thanks for the replies; 感谢您的答复; but then, how can I use Unnamed Namespaces, and for what purpose? 但是,然后,我该如何使用未命名命名空间?其用途是什么?

A translation unit is basically the chunk of code that you give to a compiler to process. 转换单元基本上就是您交给编译器处理的代码块。 The compiler processes it and produces object code for the linker. 编译器处理它并为链接器生成目标代码。 The linker combines the object code from all of your translation units to form the executable. 链接器将所有翻译单元的目标代码组合在一起,形成可执行文件。 (Sometimes you'll see details that vary from this, such as not seeing a file for the object code when you have only one translation unit. The concept is still valid even though implementation details may vary.) (有时,您会看到与此不同的细节,例如,只有一个翻译单元时,看不到目标代码文件。即使实现细节可能有所不同,该概念仍然有效。)

So typically, there is a one-to-one correspondence between .o (or .obj ) files produced when compiling and translation units. 因此,通常,在编译和转换单元时生成的.o (或.obj )文件之间存在一一对应的关系。 Also typically, you get one .o file for each .cpp file. 通常,每个.cpp文件都会得到一个.o文件。 Hence, it's typically reasonable to consider each .cpp file to be its own translation unit. 因此,通常将每个.cpp文件视为自己的翻译单元是合理的。 Until you do something unconventional. 直到您做一些非常规的事情。

When you use an #include directive, you tell the compiler to replace that one line with the entire contents of the included file. 使用#include指令时,您告诉编译器用所包含文件的全部内容替换这一行。 That is, the chunk of code given to the compiler includes the code from both the original file and the included file. 即,提供给编译器的代码块包括来自原始文件和包含文件的代码。 If you include one .cpp file into another, the chunk of code given to the compiler will include the code from two .cpp files, breaking the equivalence between .cpp files and translation units. 如果将一个.cpp文件包含到另一个文件中,则提供给编译器的代码块将包含来自两个.cpp文件的代码,从而打破了.cpp文件和转换单元之间的等效性。 This is generally considered a Bad idea. 通常认为这是一个坏主意。


Let's look at an example. 让我们看一个例子。 Suppose you had a file named ext.cpp that contained the following: 假设您有一个名为ext.cpp的文件,其中包含以下内容:

namespace
{
    void extFunction()
    {
        std::cout << "Called Unnamed Namespace's function.\n";
    }
}

Also suppose you had a file named main.cpp that contained the following: 还要假设您有一个名为main.cpp的文件,其中包含以下内容:

#include <iostream>
#include "ext.cpp"


int main()
{
    extFunction();
    return 0;
}

If you were to compile main.cpp , one of the first things the compiler would do is preprocess main.cpp . 如果要编译main.cpp ,则编译器要做的第一件事就是预处理main.cpp This modifies the file's contents, changing what the compiler sees. 这将修改文件的内容,从而更改编译器的外观。 After preprocessing, the chunk of code that the compiler will process would look like the following. 预处理之后,编译器将处理的代码块如下所示。

[lots of code from the library header named "iostream"]
namespace
{
    void extFunction()
    {
        std::cout << "Called Unnamed Namespace's function.\n";
    }
}


int main()
{
    extFunction();
    return 0;
}

At this point, there is no problem calling extFunction since the compiler sees the unnamed namespace in the chunk of code it is processing. 此时,调用extFunction是没有问题的,因为编译器会在正在处理的代码块中看到未命名的名称空间。


Another example for the requested information about using unnamed namespaces. 有关使用未命名名称空间的所请求信息的另一个示例。 Similar to the above, but different. 与上述类似,但有所不同。 Suppose you had a file named ext.cpp that contained the following: 假设您有一个名为ext.cpp的文件,其中包含以下内容:

#include <iostream>
namespace
{
    void extFunction()
    {
        std::cout << "Called Unnamed Namespace's function in EXT.\n";
    }
}

void extPublic()
{
    extFunction();
}

Let's also provide a header ( ext.h ) that will declare the function that has external linkage. 我们还提供一个标头( ext.h ),该标头将声明具有外部链接的函数。

void extPublic();

Now move on to main.cpp : 现在转到main.cpp

#include <iostream>
#include "ext.h"  // <-- Including the header, not the source.

namespace
{
    void extFunction()
    {
        std::cout << "Called Unnamed Namespace's function in MAIN.\n";
    }
}
int main()
{
    extFunction();
    extPublic();
    return 0;
}

Look at that! 看那个! There are two definitions for the function named extFunction ! 函数extFunction有两个定义! Won't the linker get confused? 链接器不会感到困惑吗? Not at all. 一点也不。 Those functions are not seen outside their translation units, so there is no conflict. 这些功能不会在其翻译部门之外看到,因此没有冲突。 If you compile main.cpp , compile ext.cpp , and link main.o and ext.o into a single executable, you get the following output. 如果编译main.cpp ,编译ext.cpp ,并将main.oext.o链接到单个可执行文件中,则会得到以下输出。

Called Unnamed Namespace's function in MAIN. 在MAIN中称为“未命名命名空间”的函数。
Called Unnamed Namespace's function in EXT. 在EXT中称为未命名命名空间的函数。

One benefit of an unnamed namespace is that you don't have to worry about conflicting with names in another source file's unnamed namespace. 未命名名称空间的一个好处是,您不必担心与另一个源文件的未命名名称空间中的名称冲突。 (This becomes a much bigger benefit when your project grows to encompass hundreds of source files.) (当您的项目增长到包含数百个源文件时,这将带来更大的好处。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM