网站首页 > 文章精选 正文
1、奇怪的现象
在C++多文件编译的时候,很多人都会经常碰见这样的一种情况,在一个cpp文件中调用另一个cpp文件的函数,那么可以直接调用吗?我们来做个试验。
有以下三个文件main.cpp,cal.h,cal.cpp
//main.cpp
#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
#include <stdio.h>
int add(int x, int y);
//cal.cpp
#include "cal.h"
int add(int x, int y)
{
return x + y;
}
那么请问,我如果直接在main.cpp文件中直接调用cal.cpp中的函数方法可以吗?或者我换种方式问,请问可以编译通过吗?可以运行通过输出结果吗?
我在网上搜寻答案的时候,发现有些人表示可以很顺利地运行通过,而有些人表示完全按照提示的方法,复制黏贴,却报了找不到函数方法的错误:
undefined reference to `add(int, int)'
那么请问到底是怎么回事呢?千万不要觉得说肯定是他们漏复制了什么,漏了函数声明什么的,这些都不是原因。那么是什么原因呢?
2、真正的原因
真正的原因是IDE在搞鬼!
首先我们要明白一下,像C/C++、java等高级语言编译生成可执行文件是要经历预处理、编译、汇编、链接这几个过程,像以上三个文件,头文件仅仅只参与到预处理过程,将cal.h的内容包含到另外两个cpp文件中,而另外两个cpp文件是要经历编译、汇编生成机器语言的二进制文件,也就是说两个cpp都会各自生成各自的二进制文件。
但是这个还没完,要生成可执行文件,还要将以上cpp文件生成的二进制文件进行链接起来,并且有个文件中还要提供一个main函数入口,因为C++语言的可执行文件的入口是main函数,不提供的话程序无法运行。
如果在Linux平台上要清楚地展现,就是以下这几个语句:
gcc -c main.cpp //会生成main.o文件
gcc -c add.cpp //会生成add.o文件
gcc main.o add.o -o main
生成的.o文件就是二进制文件,然后将二进制文件进行链接生成可执行文件,也可以用以下这个语句一步到位:
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()这个函数的接口,而我不想把函数具体的实现也提供出来,像在网络上如果应用第三方库的时候,别人不希望把他们的源码提供出来,但是又想提供这个接口给调用者调用,那么这时候该怎么做呢?
方法是有,下回分解。
更多精彩内容,请关注同名公众:一点月光(alittle-moon)
猜你喜欢
- 2025-06-28 程序员C/C++你不得不看的27个优化建议
- 2025-06-28 [c++面试题]数据库中的outer join, 你了解吗?
- 2025-06-28 开机弹出 C++ Runtime Library: Assertion failed窗口解决方法
- 2025-06-28 C++调用外部程序传递用户名密码登录
- 2025-06-28 C++编程:标准库visit和variant用法
- 2025-06-28 C/C++编程推荐学习顺序和书籍(c++编程需要学多久)
- 2025-06-28 c/c++如何避免头文件被多次包含(c语言避免头文件重复定义)
- 2025-06-28 C++20 香不香?从四大新特性看起(c++20支持)
- 2025-06-28 C++知识点 13:extern“C”(c语言extern的用法)
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)