C++程序编译之谜——多文件编译的奇怪现象

左手编程,右手年华。大家好,我是一点,关注我,带你走入编程的世界。

公众号:一点sir,关注领取编程资料

1、奇怪的现象

在C++多文件编译的时候,很多人都会经常碰见这样的一种情况,在一个cpp文件中调用另一个cpp文件的函数,那么可以直接调用吗?我们来做个试验。

有以下三个文件main.cpp,cal.h,cal.cpp main.cpp

c 复制代码
#include <stdio.h>
#include "cal.h"
int main(int argc, char *argv[])
{
    printf("add(5,4) is %d\n", add(5, 4));
    return 0;
}

cal.h

c 复制代码
//cal.h
#include <stdio.h>
int add(int x, int y);

cal.cpp

c 复制代码
//cal.cpp
#include "cal.h"
int add(int x, int y)
{
    return x + y;
}

那么请问,我如果直接在main.cpp文件中直接调用cal.cpp中的函数方法可以吗?或者我换种方式问,请问可以编译通过吗?可以运行通过输出结果吗?

我在网上搜寻答案的时候,发现有些人表示可以很顺利的运行通过,而有些人表示完全按照提示的方法,复制黏贴,却报了找不到函数方法的错误:

csharp 复制代码
undefined reference to `add(int, int)'

那么请问到底是怎么回事呢?千万不要觉得说肯定是他们漏复制了什么,漏了函数声明什么的,这些都不是原因。那么是什么原因呢?

2、真正的原因

真正的原因是IDE在搞鬼!

首先我们要明白一下,像C/C++、java等高级语言编译生成可执行文件是要经历预处理、编译、汇编、链接这几个过程,像以上三个文件,头文件仅仅只参与到预处理过程,将cal.h的内容包含到另外两个cpp文件中,而另外两个cpp文件是要经历编译、汇编生成机器语言的二进制文件,也就是说两个cpp都会各自生成各自的二进制文件。

但是这个还没完,要生成可执行文件,还要将以上cpp文件生成的二进制文件进行链接起来,并且有个文件中还要提供一个main函数入口,因为C++语言的可执行文件的入口是main函数,不提供的话程序无法运行。

如果在Linux平台上要清楚的展现,就是以下这几个语句:

less 复制代码
gcc -c main.cpp  //会生成main.o文件
gcc -c add.cpp   //会生成add.o文件
gcc main.o add.o -o main

生成的.o文件就是二进制文件,然后将二进制文件进行链接生成可执行文件,也可以用以下这个语句一步到位:

css 复制代码
gcc add.cpp main.cpp -o main

这样子的话在运行可执行文件,就会输出正确结果,不会报错了。

那么我们再回到开头的那个问题,为什么有些人可以正确的输出不会报错,而有些人却会报错呢?首先我猜测他们都是在window平台执行的,并且是用IDE来编译的,而不同的IDE功能都各不相同,有些IDE非常的智能,它可能会根据在main文件中导入的h文件自动去寻找对应的cpp文件,比如像上面我在main.cpp文件中导入了add.h的头文件,那么IDE会自动去寻找看看是否有add.cpp文件,有的话进行编译、链接,输出结果。

当然,这些只是我的猜测,可能IDE也有其他办法可以找出文件间的关系,然后进行编译。不管如何,有些IDE中确实是可以实现这样子的功能,但有些比较简单的IDE就没有这么智能了,这时候可能就会报以上错误,这个可能就需要你进行某些设置,至于如何设置,这个不同IDE都不相同,大家可以自己去网上搜搜答案。

3、新的疑团

那么可能有些人这时候会提出一个疑问,如果我只想提供add()这个函数的接口,而我不想把函数具体的实现也提供出来,像在网络上如果应用第三方库的时候,别人不希望把他们的源码提供出来,但是又想提供这个接口给调用者调用,那么这时候该怎么做呢?

方法是有,下回分解。

相关推荐
喵~来学编程啦7 小时前
【编译原理】编译原理知识点汇总·词法分析器(正则式到NFA、NFA到DFA、DFA最小化)
学习笔记·编译原理
喵~来学编程啦2 天前
【编译原理】编译原理知识点汇总·概论与文法
学习笔记·编译原理
Trouvaille ~3 个月前
【C++篇】C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略
c++·c++20·编译原理·编译器·类和对象·rvo·nrvo
无名之逆4 个月前
B树和B+树
javascript·数据结构·b树·算法·编译原理·期末速成
嚯呀怪怪怪4 个月前
从零基础学Go(九)——Go的Goroutine
golang·线程·多线程·并发·编译原理·协程·gorountine
Beginner x_u6 个月前
编译原理 第二章下: 推导,规约,句型句子,语言,文法分类,二义性
编译原理·语言·推导·文法
codists6 个月前
《编译原理》阅读笔记:p19-p24
编译原理
Beginner x_u6 个月前
编译原理 第一章: 编译概述 重点总结(翻译程序的过程,解释程序,编译程序的结构)
编译原理·解释程序·翻译程序·编译概述
Beginner x_u6 个月前
编译原理 第三章上 :词法分析 状态图的画法与检验
编译原理·词法分析·状态图
codists6 个月前
《编译原理》阅读笔记:p18
编译原理