The Cherno C++笔记 03

目录

[Part 07 How the C++ Linker Works](#Part 07 How the C++ Linker Works)

1.链接

2.编译链接过程中出现的错误

[2.1 缺少入口函数](#2.1 缺少入口函数)

注意:如何区分编译错误还是链接错误

注意:入口点可以自己设置

[2.2 找不到自定义函数](#2.2 找不到自定义函数)

2.2.1缺少声明

2.2.2自定义函数与引用函数不一致

[2.3 在头文件中放入定义](#2.3 在头文件中放入定义)

[2.3.1 多次定义](#2.3.1 多次定义)

[2.3.2 头文件不要放定义](#2.3.2 头文件不要放定义)


Part 07 How the C++ Linker Works

1.链接

每个源文件都会被编译器编译成机器码.obj目标文件,接下来将这些obj目标文件组合成一个可执行的程序就需要链接。"链接" 就是指将多个源文件编译成一个可执行文件的过程。


2.编译链接过程中出现的错误

2.1 缺少入口函数

我们简单写一个乘法函数

Multiply.cpp

复制代码
int Multiply(int a, int b)
{
	int z = a * b;
	return z;
}

Ctrl+F7 编译

成功编译

Crtl+F5 编译+链接

缺少主函数,链接错误


注意:如何区分编译错误还是链接错误

编译错误

Multiply.cpp

复制代码
int Multiply(int a, int b)
{
	int z = a * b;
	return z//故意少个分号
}

链接错误


注意:入口点可以自己设置

在 C++ 程序中,程序的入口点通常是 main 函数。然而,有时你可能希望自定义程序的入口点,这可以通过使用不同的入口函数和链接选项来实现。


2.2 找不到自定义函数

2.2.1缺少声明

我们在建立一个.cpp文件

Main.cpp

复制代码
#include <iostream>
int main()
{
	std::cout << Multiply(2, 5) << std::endl;
	std::cin.get();
}

编译链接发现报错

因为编译这个文件的时候不知道有这个函数

声明一下就可以

复制代码
int Multiply(int a, int b);

2.2.2自定义函数与引用函数不一致

如果我们在定义函数的时候将Multiply写错

复制代码
int Multipl(int a, int b)
{
	int z = a * b;
	return z;
}

编译链接,链接错误,改函数名即可


2.3 在头文件中放入定义

2.3.1 多次定义

首先先看一个比较明显的错误

我们再引入Log函数

Log.cpp

复制代码
#include <iostream>
void Log(const char* message)
{
	std::cout << message << std::endl;
}
//定义Log函数

Multiply.cpp

复制代码
int Multiply(int a, int b)
{
	int z = a * b;
	return z;
}

Main.cpp

复制代码
#include <iostream>
int Multiply(int a, int b);

void Log(const char* message)
{
	std::cout << message << std::endl;
}
//把Log 函数再定义一遍

int main()
{
	Log("2*5");
	std::cout << Multiply(2, 5) << std::endl;
	std::cin.get();
}

然后编译链接,链接错误

已经定义过了,这很显然,因为多次定义,链接器不知道链接哪一个。

2.3.2 头文件不要放定义

但是如果把定义放在头文件,可能就不容易发现了。

Log.h

复制代码
#include <iostream>
void Log(const char* message)
{
	std::cout << message << std::endl;
}

Multiply.cpp(使用Log函数)

复制代码
#include "Log.h"
//包含Log.h 头文件
int Multiply(int a, int b)
{
	Log("乘法函数");//使用Log函数
	int z = a * b;
	return z;
}

Main.cpp(使用Log函数)

复制代码
#include <iostream>
int Multiply(int a, int b);

#include "Log.h"
//包含Log.h 头文件

int main()
{
	Log("2*5");//使用Log函数
	std::cout << Multiply(2, 5) << std::endl;
	std::cin.get();
}

编译链接,连接错误,多次定义(因为include 的本质是复制粘贴)

而如果我们将定义放在一个单独的cpp文件,头文件只用来声明,就没有这个顾虑

Log.h

复制代码
void Log(const char* message);

Log.cpp

复制代码
#include <iostream>
void Log(const char* message)
{
	std::cout << message << std::endl;
}

其余保持不变

成功!!

还有一种方法:inline

inline 指的是:inline 是 C++ 中的一个关键字,用于向编译器建议将函数的定义插入到调用处,而不是生成函数调用的代码,其实就是直接把函数体的内容替换过去

Log.h

复制代码
#include <iostream>
inline void Log(const char* message)
{
	std::cout << message << std::endl;
}

这样即可

相关推荐
apihz11 分钟前
域名WHOIS信息查询免费API使用指南
android·开发语言·数据库·网络协议·tcp/ip
珹洺24 分钟前
C++算法竞赛篇:DevC++ 如何进行debug调试
java·c++·算法
coding随想25 分钟前
掌控网页的魔法之书:JavaScript DOM的奇幻之旅
开发语言·javascript·ecmascript
Norvyn_734 分钟前
LeetCode|Day18|20. 有效的括号|Python刷题笔记
笔记·python·leetcode
爱吃烤鸡翅的酸菜鱼44 分钟前
IDEA高效开发:Database Navigator插件安装与核心使用指南
java·开发语言·数据库·编辑器·intellij-idea·database
心情好的小球藻1 小时前
Python应用进阶DAY9--类型注解Type Hinting
开发语言·python
惜.己2 小时前
使用python读取json数据,简单的处理成元组数组
开发语言·python·测试工具·json
Y4090012 小时前
C语言转Java语言,相同与相异之处
java·c语言·开发语言·笔记
笑衬人心。2 小时前
TCP 拥塞控制算法 —— 慢启动(Slow Start)笔记
笔记·tcp/ip·php
花海如潮淹2 小时前
前端性能追踪工具:用户体验的毫秒战争
前端·笔记·ux