首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++翻译股

C++翻译股
EN

Stack Overflow用户
提问于 2019-03-31 14:19:45
回答 1查看 1.1K关注 0票数 1

我并不真正理解翻译单元是什么以及如何使用未命名的命名空间:

如果我有一个.cpp文件:

代码语言:javascript
复制
namespace
{
    void extFunction()
    {
        std::cout << "Called Unnamed Namespace's function.\n";
    }
}

和一个主要的.cpp文件:

代码语言:javascript
复制
#include <iostream>
#include "ext.cpp"

using namespace std;

int main()
{
    extFunction();


    return 0;
}

为什么我可以从另一个文件访问未命名名称空间的成员?

编辑:

谢谢您的回复;但是,我如何使用未命名的名称空间,以及用于什么目的呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-31 19:00:01

翻译单元基本上是给编译器处理的代码块。编译器处理它并为链接器生成对象代码。链接器将来自所有翻译单元的目标代码组合成可执行文件。(有时,您会看到与此不同的详细信息,例如在只有一个翻译单元时看不到对象代码的文件。尽管实现细节可能有所不同,但这一概念仍然有效。

因此,通常在编译和翻译单元时生成的.o (或.obj)文件之间有一对一的对应关系。通常,每个.o文件都有一个.cpp文件。因此,通常认为每个.cpp文件都是它自己的翻译单元是合理的。直到你做了一些非常规的事。

当您使用#include指令时,您告诉编译器用包含的文件的全部内容替换这一行。也就是说,提供给编译器的代码块包括原始文件和包含文件的代码。如果将一个.cpp文件包含到另一个文件中,则给编译器的代码块将包含来自两个.cpp文件的代码,从而破坏了.cpp文件和翻译单元之间的等价性。这通常被认为是一个糟糕的想法。

让我们看一个例子。假设您有一个名为ext.cpp的文件,该文件包含以下内容:

代码语言:javascript
复制
namespace
{
    void extFunction()
    {
        std::cout << "Called Unnamed Namespace's function.\n";
    }
}

另外,假设您有一个名为main.cpp的文件,该文件包含以下内容:

代码语言:javascript
复制
#include <iostream>
#include "ext.cpp"


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

如果要编译main.cpp,编译器首先要做的事情之一就是对main.cpp进行预处理。这会修改文件的内容,从而改变编译器所看到的内容。预处理后,编译器将处理的代码块如下所示。

代码语言:javascript
复制
[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;
}

此时,调用extFunction没有问题,因为编译器在它正在处理的代码块中看到了未命名的命名空间。

有关使用未命名命名空间的请求信息的另一个示例。类似于上面的,但不同。假设您有一个名为ext.cpp的文件,该文件包含以下内容:

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

void extPublic()
{
    extFunction();
}

让我们还提供一个标头(ext.h),它将声明具有外部链接的函数。

代码语言:javascript
复制
void extPublic();

现在转到main.cpp

代码语言:javascript
复制
#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;
}

看那儿!函数有两个定义,名为extFunction!链接器不会被弄糊涂吗?不用谢。这些职能不在翻译单位之外,因此不存在冲突。如果编译main.cpp,编译ext.cpp,并将main.oext.o链接到单个可执行文件中,则会得到以下输出。

在MAIN中调用未命名的Namespace函数。 在EXT中调用未命名的Namespace函数。

未命名命名空间的一个好处是,您不必担心与另一个源文件的未命名命名空间中的名称冲突。(当项目扩展到包含数百个源文件时,这将带来更大的好处。)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55441843

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档