【问题标题】:How c++ includes all functions in specific file without any inclusion of that file?c++ 如何在不包含该文件的情况下包含特定文件中的所有函数?
【发布时间】:2016-05-07 10:34:26
【问题描述】:

我只是觉得它是如何工作的? 这是我第一次看到,位于同一目录“Test1.cpp,Test2.cpp”中的两个 c++ 文件

Test1.cpp:

#include <iostream>
void magic();
int main(){
    magic();
return 0;
}

Test2.cpp:

#include <iostream>

using namespace std;
void magic(){
    cout << "That's not a magic , it's a logical thing.." << endl;
}

正如我上面提到的,它们在同一个目录中,具有“魔术”功能的原型。 现在我的问题是,如果不包含任何 Test2.cpp,魔术是如何工作的? C++ 默认包含它吗?如果这是真的,那么为什么我们需要包含我们的课程?为什么我们需要头文件而cpp文件可以达到目的?

【问题讨论】:

  • 您要查找的过程称为链接。链接使用外部链接标识名称,因此两个文件中的名称 magic 指向链接中的同一实体。所有名称都引用已定义(而不仅仅是声明)实体的链接可用于创建可执行程序或库。
  • 声明 void magic(); 告诉编译器将有一个具有此签名的函数 - 稍后在同一文件中或在链接时 - 因此您将能够在代码中使用它。 What is the difference between a definition and a declaration?.
  • 您可以使用Test2.h 来声明magic,但这已经在Test1.cpp 中,在Test1.cpp 中不需要它,在Test2.cpp 中也不需要它的定义。跨度>
  • C++ 没有原型;相反,我们只是说您声明 magic,或者Test1.cpp 包含“magic 声明”。术语“原型”用在 C 中,这是一种具有不同规则的不同语言。在这方面,C++ 比 C 更简单。
  • 在 Test.cpp void magic();向编译器指示在某处定义了函数魔法。这种依赖将在点赞阶段得到解决。

标签: c++


【解决方案1】:

为了从 C++ 源代码中获取可执行文件,需要两个主要阶段:

  • 编译阶段;
  • 链接阶段。

第一个只搜索函数的签名并检查函数调用是否与找到的声明兼容。

第二个是在通过链接器命令行指定的选项链接的库或对象中搜索函数的实现(有些编译器可以自动运行链接器添加一些命令行选项)。

所以你需要了解编译器和链接器选项才能理解这个过程。

【讨论】:

  • 如果你想学究气,你应该提到编译器本身不做链接。 GNU 工具链调用ld 来进行链接,但您也可以将目标文件打包到ar 中并完全避免ld
  • 谢谢,考虑到您的建议,我刚刚进行了编辑以改进响应。
【解决方案2】:

头文件的主要作用是简化代码的编写。

让我们考虑下一个例子:

test2.cpp

#include <iostream>

using namespace std;

void my ()
{ magic(); } // here we don't know what magic() is and compiler will complain

void magic(){
  cout << "That's not a magic , it's a logical thing.." << endl;
}

这段代码给出了下一个错误:

gaal@linux-t420:~/Downloads> g++ test2.cpp 
test2.cpp: In function ‘void my()’:
test2.cpp:6:9: error: ‘magic’ was not declared in this scope
 { magic(); } // here we don't know what magic() is and compiler will complain
         ^

为了避免这个错误,我们需要将magic() 函数的声明放在my() 的定义之前。因此,将所有声明放在一个地方是个好主意。头文件就是这样一个地方。如果我们不使用标头,我们需要将 magic() 函数的声明粘贴到将要使用它的任何 cpp 文件中。

【讨论】:

  • @GerogeGaal ,这是否意味着如果我删除了魔法声明“void magic();”这将是链接器错误? (缺少定义)?
  • 不是链接器错误,而是编译器错误。我编辑了答案。请查看具体错误。
  • 哦,是的,但是如果我们在没有定义的情况下声明它,那将是链接器错误,对吗?
猜你喜欢
  • 1970-01-01
  • 2012-09-19
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-01
  • 2023-03-16
相关资源
最近更新 更多