首页 > 编程语言 >C++链接的那些事

C++链接的那些事

时间:2024-09-15 18:21:22浏览次数:3  
标签:文件 Log 函数 C++ 链接 那些 我们 log

接上文

OK! Right now!   Let's  go!

今天我们来谈谈链接,什么是链接,C++链接实际上做什么的?

链接是一个过程,当我们从源C++文件转到实际的可执行文件(二进制文件)。第一阶段是编译源文件,一旦我们把文件编译好,就需要通过一个叫做链接的过程,现在链接的主要工作是找到每个符号和函数在哪里,并把他们链接起来。记住,每个文件被编译成一个单独的目标文件,他们彼此之间没有关系,这些文件不能交互。所以如果我们决定把我们的程序分割成多个C++文件,我们需要一种方法把这些文件连接在一起成一个项目,而这就是链接器的主要目的和要做的事情。

要记住我们要生成一段代码有两个阶段,一是编译,而是链接。如果只ctrl+F7(编译),如果F5(生成)那就是编译并链接,所以这两个操作可能会得到不同类型的错误。如果我们犯了语法错误,编译器会报错

这个代表链接,她告诉我们这个错误发生在链接阶段

我们可以看到配置类型是exe文件,这种文件必须要有某种入口点。一般默认是main函数,但实际我们可以更改这个函数名,也就是入口点不一定必须是一个叫main的函数。在链接器高级入口点选项可以看到我们可以指定一个自定义的入口点。

如果我们加上main函数可以看到成功运行生成了一个.exe文件

接下来我们看链接失败的几种情况:

我们可能会遇到一种错误,叫做未解决的外部符号unresolved external symbol,这就是当链接器找不到他需要的东西时发生的。

他认为在 某个地方有一个log函数,但这是链接的工作,就是找log函数的阶段。

如果我现在构建整个项目,你会看到实际上我们得到了一个错误

他告诉我们丢失了什么符号,他是Log函数,他甚至告诉我们在哪里引用了他(在Multiply函数中)

现在我们注释掉这个log函数,我们不去调用它,

如果我试着build下,没有错误,发生这种情况的原因是我从来没有调用过log函数,所以链接器不需要去链接这个log函数。

另一个有趣的是,

我注释了这一行,即我从来没有调用过Multiply函数,也就不会调用log函数了,如果我现在build我的项目

你会看到我仍然得到了一个链接错误,你可能会说why?!

我没有在任何地方调用Multiply函数,为什么他会抱怨链接错误,我们可不可以说这些没用的死代码一点意义都没有呢?

大错特错!因为在这个文件里,虽然我们不用Multiply函数,但技术上讲,我们在另一个文件中可能使用它。所以链接器确实需要链接它。

如果我们能告诉编译器,嘿这个Multiply函数,我只会在这个文件中使用它,不会在其他文件中使用它,我们可以去掉这种链接的必要性,因为Multiply从来不会被调用,也就是从不需要调用log函数,可以通过一个方法做到。

如果我把这个函数名称改回来,并修改了返回值类型

原因是我们的链接器要寻找一个名叫log的函数,她的返回值是void以及参数是const char* message。同样的函数名,返回值,参数。我们的链接器才会链接成功。

另一种链接错误很常见,就是我们有重复的符号,换句话说,我们的函数或变量,有相同的名字、两个名字相同的函数有相同的返回值和相同的参数。如果发生这种情况,我们就有麻烦了,不知道该链接到哪一个。

只编译这个Log.cpp文件就可以发现问题。

如果我们不写在一起,把一个写在math文件中

只编译他就不会发现问题但如果我们build整个项目,我们会得到一个链接错误,

当然以上错误太明显了

以下为一种不常发现的错误

这是因为#include头文件的作用,所以我们有几种解决方法:

①我们在Log.h文件中的Log函数前面加上static,之后log和math文件都会有自己版本的log函数

加上static后,它对任何其他的obj文件都不可见

现在我们build整个项目,ok了

②我们在Log.h文件中的Log函数前面加上inline,inline的意思是获取我们实际的函数体并将函数调用替换为函数体

变成下面这个

其他不变

 

③还有一种方法,就是把Log函数的定义移到一个翻译单元。因为现在的情况是这个log函数的定义列入了两个翻译单元(Log.cpp和math.cpp),这是导致错误的主要原因,我们可以把他搬到第三个翻译单元(这里因为有同名的文件,所以就放在Log.cpp中)

在工作结束以后,链接器需要带走我们所以的目标文件,并将他们链接在一起。他也将可能被拉进我们可能用到的其他任何库,例如C运行时库,如果有必要,C++的标准库,平台的api等等。从许多不同的地方链接是很正常的。还有很多不同类型的链接,静态链接和动态链接。

标签:文件,Log,函数,C++,链接,那些,我们,log
From: https://blog.csdn.net/2401_87088772/article/details/142287035

相关文章

  • C++编译 链接 执行那些事
    OK!Rightnow!  Let's go!如何从源文件开始,实际的文本文档到可执行的二进制代码,写C++程序的基本流程。实际是你有一些C++的源文件,然后将这些源文件给到编译器,编译器将其转成二进制的东西,二进制的东西可能是某种库,或者是可执行的程序。在#符号之后的都是预处理语句......
  • 「数组」堆排序 / 大根堆优化(C++)
    目录概述核心概念:堆堆结构数组存堆思路算法过程up()down()Code优化方案大根堆优化Code(pro)复杂度总结概述在「数组」快速排序/随机值优化|小区间插入优化(C++)中,我们介绍了三种基本排序中的冒泡排序与分治思想结合的算法:快速排序。本文我们来讲第二种基本排......
  • 详解c++多态---上
    virtual关键字1.可以修饰原函数,为了完成虚函数的重写,满足多态的条件之一。classPerson{public:virtualvoidBuyTicket(){cout<<"买票-全价"<<endl;}};classStudent:publicPerson{public:virtualvoidBuyTicket(){cout<<"买票-半价"<<......
  • c++走出迷宫改良版2
    本文对上期做了删改话不多说上代码:注彩色输出部分代码出自博主夜若渊#include<bits/stdc++.h>#include<windows.h>#include<stdlib.h>#include<cstdio>#include<iostream>#include<string>#include<stdio.h>#include<ctime>#include<conio.h&g......
  • 深入解析C++函数指针:掌握游戏开发中的关键技术
    深入解析C++函数指针:掌握游戏开发中的关键技术C++作为一门经典的编程语言,因其强大的性能和灵活性,被广泛应用于游戏开发。而函数指针作为C++中的一个重要概念,在游戏开发中更是扮演着不可或缺的角色。对于想要深入掌握C++并在游戏开发领域站稳脚跟的开发者来说,理解并灵活运用函数指......
  • 帝国CMS提示“您来自的链接不存在”怎么解决?
    当帝国CMS提示“您来自的链接不存在”时,这通常意味着系统无法找到或识别你尝试访问的链接。这种情况可能由多种原因造成,以下是一些常见的解决方法:1.检查链接地址确认链接地址:首先确认你尝试访问的链接地址是否正确,包括拼写错误或格式问题。清除缓存:有时候浏览器缓存可能导致......
  • 漫话linux:基础IO,软硬链接,动静态库管理
    1.软硬链接    1.软链接:是一个独立文件,具有独立的inode,也有独立的数据块,它的数据块里面保存的是指向的文件的路径,公用inode        1.建立软连接ln-s目标文件或目录,链接名 目标文件或目录表示路径,链接名代表命令,无论在哪里输入命令就能调......
  • C++入门补充语法
    1、C和C++的区别                首先C++是包含C语言的,C语言中的所有语法在C++中都可以应用,因为C语言语法限制过多导致许多东西实现起来不方便,所以C++又制订了一系列的语法来补充C语言的不足。2、命名空间2.1命名空间为什么要使用命名空间,下面我们使用一段......
  • C++资源管理浅谈
    引言:            在计算机编程语言的学习与实践中,自然避免不了与计算机的资源管理打交道。所谓的资源就是,一旦用了它,将来就必须还给系统,如果用户不这么做,那糟糕的事情便会发生。在开始谈及C++的资源管理之前,先来聊聊何为计算机的资源,以及为何要管理计算机的资......
  • 【C++】string类中常用函数的模拟实现
    【C++】string类中常用函数的模拟实现1.string.h2.Text.cpp1.string.h#include<assert.h>namespacewch{ classstring { public: typedefchar*iterator; typedefconstchar*const_iterator; iteratorbegin() { return_str; } itera......