【发布时间】:2013-05-05 23:04:26
【问题描述】:
我正在阅读 Scott Meyer 的 Effective C++ 的第 4 项,他试图展示一个在不同翻译单元中使用静态非本地对象的示例。他强调了一个问题,即在一个翻译单元中使用的对象在使用之前不知道它是否已在另一个翻译单元中初始化。如果有人有副本,它在第三版的第 30 页。
例子是这样的:
一个文件代表一个库:
class FileSystem{
public:
std::size_t numDisks() const;
....
};
extern FileSystem tfs;
在客户端文件中:
class Directory {
public:
Directory(some_params);
....
};
Directory::Directory(some_params)
{
...
std::size_t disks = tfs.numDisks();
...
}
我的两个问题是:
1) 如果客户端代码需要使用tfs,那么就会有某种包含语句。因此,该代码肯定都在一个翻译单元中吗?我看不出您如何引用不同翻译单元中的代码?程序肯定是一个翻译单元吗?
2) 如果客户端代码包含 FileSystem.h,extern FileSystem tfs; 行是否足以让客户端代码调用 tfs(我很欣赏初始化可能存在运行时问题,我只是在谈论编译时范围)?
编辑到第一季度
书上说这两段代码位于不同的翻译单元中。客户端代码如何使用变量tfs,知道它们在不同的翻译单元中??
【问题讨论】:
-
“程序肯定是一个翻译单元吗?”一个翻译单元基本上由一个 cpp 文件(源文件)加上包含的文件(标题)减去条件包含(
#if)组成。因此,您可以将多个翻译单元组成一个程序(它们在最后一个翻译阶段由链接器链接在一起)。 -
@DyP 我不明白代码如何在没有标头的情况下链接到其他代码?
-
你需要有一个变量/函数的声明或者一个类的定义才能使用它。您可以通过
#include做到这一点,这实际上是将标头内容复制粘贴到源文件 (cpp) 中。链接器匹配使用外部链接声明的名称,例如在您的示例中,任何翻译单元中tfs的声明与定义它的翻译单元中tfs的定义。 -
@DyP 据我了解,使用#include 暗示我们在同一个翻译单元中?翻译单元是源文件,加上它#includes 到的所有头文件?
-
编译器从输入源文件开始。它需要一个源文件,解析所有
#includes 和#ifs,然后有一个翻译单元。然后它继续翻译那个翻译单元。对所有其他源文件(-> 许多 TU)重复(独立)。最后,将所有翻译单元(现在是目标文件)组合起来形成程序。
标签: c++