网站首页 > 精选文章 正文
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-07-01 Java中的native方法(native java api)
- 2025-07-01 JAVA工程师面试考试测试题(Java面试题HR必备)
- 2025-07-01 干货 | Java语言这10个语言特性你知道吗?
- 2025-07-01 JavaCPP快速入门(官方demo增强版)
- 2025-07-01 Java编程入门第一课:HelloWorld(java编程如何入门)
- 2025-07-01 JVM系列之ClassLoader(jvm classloader)
- 2025-07-01 深入理解Java虚拟机之自己编译JDK
- 2025-07-01 函数入口一定是main吗?为什么不指定编译生成文件名, 默认是a.out?
- 2025-07-01 新手小白学Java|零基础入门笔记|原来学Java可以这么简单
- 2025-07-01 15.将一个给定的PDF文档拆分为多个文档(JAVA+PDFBOX)
- 07-03CentOS7系统如何修改主机名(更改centos主机名)
- 07-03Ubuntu1804 及以上版本的 Coredump 相关设置
- 07-03Linux中如何修改ip地址?(linux系统怎么更改ip地址)
- 07-03Linux系统日常运维九大核心技能(linux运维都干什么)
- 07-03Linux 日志管理攻略:用 journalctl 揪出服务器安全隐患
- 07-03Linux下快速安装ollama和deepseek并使用web界面
- 07-03RockyLinux9.5下使用ollama搭建本地AI大模型DeepSeek
- 07-03Linux 下的 PM2 完整指南(linux /media)
- 最近发表
-
- CentOS7系统如何修改主机名(更改centos主机名)
- Ubuntu1804 及以上版本的 Coredump 相关设置
- Linux中如何修改ip地址?(linux系统怎么更改ip地址)
- Linux系统日常运维九大核心技能(linux运维都干什么)
- Linux 日志管理攻略:用 journalctl 揪出服务器安全隐患
- Linux下快速安装ollama和deepseek并使用web界面
- RockyLinux9.5下使用ollama搭建本地AI大模型DeepSeek
- Linux 下的 PM2 完整指南(linux /media)
- Rocky Linux 9常用命令备忘录(不定时更新)
- Rocky Linux 9 系统初始化与安全加固脚本
- 标签列表
-
- 向日葵无法连接服务器 (32)
- git.exe (33)
- vscode更新 (34)
- dev c (33)
- git ignore命令 (32)
- gitlab提交代码步骤 (37)
- java update (36)
- vue debug (34)
- vue blur (32)
- vscode导入vue项目 (33)
- vue chart (32)
- vue cms (32)
- 大雅数据库 (34)
- 技术迭代 (37)
- 同一局域网 (33)
- github拒绝连接 (33)
- vscode php插件 (32)
- vue注释快捷键 (32)
- linux ssr (33)
- 微端服务器 (35)
- 导航猫 (32)
- 获取当前时间年月日 (33)
- stp软件 (33)
- http下载文件 (33)
- linux bt下载 (33)