C++模板不支持分离编译的问题

news2024/11/15 4:18:06

目录

    • 前言
    • 分离编译模式
    • 普通函数的分离编译(正常)
    • 模板函数的分离编译(出错)
    • 分析
    • 解决方式
    • 拓展--extern关键字
      • extern"C"
      • extern+变量
      • extern+模板--控制实例化

前言

分离编译模式

一个项目如果有多个源文件.c组成,每个源文件单独编译,形成目标文件最后通过链接器将所有的目标文件链接起来,形成一个可执行的文件。

这种就是.h头文件和.c源文件配合使用的模式;

分离式编译的优势

如果工程巨大(比如linux内核源码) , 当你只修改了其中一个工程文件.c的时候,重新编译只需要编译改动过的文件就可以了,不需要将全部工程文件.cpp全部重新编译。

普通函数的分离编译(正常)

各文件代码如下:

//"fun.h"
int fun(int a);

//"fun.cpp"
#include"fun.h"
int fun(int  a)
{
    return a;
}


//main.cpp
#include<iostream>
#include"fun.h"

int main()
{
   	cout<<fun(1)<<endl;
    return 0;
}

结果:正常编译,正常运行;

模板函数的分离编译(出错)

各文件代码如下:

//"fun.h"
template<class T>
int fun(T a);

//"fun.cpp"
template<class T>
int fun(T a)
{
    return a;
}

//main.cpp
#include<iostream>
#include"fun.h"

int main()
{
   	cout<<fun(1)<<endl;
    return 0;
}

结果:编译出错

在这里插入图片描述

分析

实例化

实例化是指编译器使用函数(或者是类)模板为特定类型生成函数(类)定义。编译器不会为函数(或者类)模板生成定义,只有当我们为函数(或者类)模板指定了一个特定类型时,编译器才会生成。编译器为特定类型的函数(或者类)模板生成定义的行为被称为实例化。


普通函数在编译时就实例化生成fun.obj目标文件;

之后main.cpp编译的时候,看到了fun.h的头文件中fun函数的声明,没有看到定义,链接器,在链接时就看到了fun.obj目标文件中fun函数实例出来的对象,进行链接;


C++规定模板函数只有在使用时实例化:

fun.cpp定义了模版方法,但是没有使用,因此目标文件fun.obj中不会有实例化的模版方法。

main.cpp只能看到函数的声明,并且链接器链接时也找不到fun.obj中的fun函数对象, 因此报错;


解决方式

  1. 将模板的声明和定义放在一个.hpp文件里,或者像C语言一样,放在两个.h中 ,总之让编译器在一个源文件,比如main.c中能同时看到模板的定义和初始化就行;
  2. extern 控制实例化

拓展–extern关键字

extern"C"


extern “C”的作用就是告诉C++编译器,将指定的函数用C规则编译;

因为函数重载,函数名修饰规则不同的原因,如果C++中调用C文件,编译可能会出错;

extern "C"的主要功能是为了能够正确实现C++代码调用C语言代码


extern+变量

声明某个变量或者函数在外部文件,直接拿来用;


extern+模板–控制实例化

上面说的模板使用时实例化,那工程很大,每个文件都需要用这个模板。都需要实例化一份?额外开销会非常严重

这时候可以extern修饰他,意味着其他文件中的模板func也能在这里用,就是说公用一份,只需要在一个源文件中实例化这个模板即可,生成的obj其他文件能链接到!

提一嘴 新标准的显示实例化指定类型,也能解决上面模板多文件实例化太多造成额外开销的问题

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

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

相关文章

Kubernetes:分享一个可以展示资源视图的 K8s开源 Web/桌面 客户端工具 Octant

写在前面 博文内容主要为 Octant 介绍以及 桌面/Web 端的安装教程涉及 Linux/Windows 的安装。理解不足小伙伴帮忙指正 其实当你什么都经历了&#xff0c;会发现&#xff0c;人生无论你怎么精心策划都抵不过一场命运的安排。 Octant 不是仪表板&#xff0c;Octant 是一个带有仪…

数据结构 最短路径课设(源码+实验报告+视频讲解)(不要钱、用了自取)

XIAN TECHNOLOGICAL UNIVERSITY 课程设计报告 实验课程名称 算法与数据结构 专 业&#xff1a; 班 级&#xff1a; 姓 名&#xff1a; 学 号&#xff1a; 实验学时&#xff1a; 指导…

Linux Debian11安装QT6开发环境

从Qt5.14开始&#xff0c;官方不提供离线安装包&#xff0c;只提供源码包和在线安装器。但是清华为我们提供了快速的在线安装方式。 一.下载清华提供的在线安装器 在线安装器下载链接 二、给在线安装器文件赋予执行权限 三、配置镜像地址运行安装器 清华源&#xff1a; ./…

7.Java判断和循环+面试相关力扣算法题详解

提示&#xff1a; 文章目录前言一、顺序结构二、分支语句(1)if语句(2)switch语句*default的位置和省略:*case穿透*switch新特性*switch和if的第三种格式各自的使用场景三、循环结构1.分类2.for循环3.while循环4.for和while的对比:5.for和while循环的区别:6.练习:四、面试时的两…

【安卓】zoo for zotero WebDAV 自动论文同步笔记

前言 前言是我写这篇博客的动机&#xff0c;可以跳过直接从“准备”开始看 之前使用mendeley管理文献&#xff0c;它不仅可以同步文件&#xff0c;还跨平台&#xff08;win、安卓等&#xff09;。但是后面&#xff0c;mendeley停止了移动平台的支持&#xff0c;导致我不能用我…

JQUERY案例

电梯导航 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…

一、pyhon准备工作篇(黑马程序猿-python学习记录)

黑马程序猿的python学习视频&#xff1a;https://www.bilibili.com/video/BV1qW4y1a7fU/ 目录 1. python官网 2. 检查是否安装完毕 3. pycharm官网 5. phcharm更换主题 6. 新建第一个python文件 7. pycharm字体大小设置 ​​​​​​​8. 设置快捷键 设置字体大小 ​​​​​​…

AJAX 简介

AJAX 是一种在无需重新加载整个网页的情况下&#xff0c;能够更新部分网页的技术。 AJAX 是什么&#xff1f; AJAX Asynchronous JavaScript and XML. AJAX 是一种用于创建快速动态网页的技术。 AJAX 通过在后台与服务器进行少量数据交换&#xff0c;使网页实现异步更新。这…

第三章 关系数据库标准语言SQL

第三章 关系数据库标准语言SQL 目录第三章 关系数据库标准语言SQL3.1 SQL概述3.1.1 产生与发展3.1.2 SQL的特点3.1.3 SQL的基本概念3.2 数据库实例3.3 数据定义3.3.1 模式的定义和删除3.2.2基本表的定义、删除和修改1.常见数据类型2.定义基本表3.修改基本表4.删除基本表5.模式和…

2. 返回传播计算方法|神经网络整体架构|神经元个数对结果的影响|正则化与激活函数|神经网络过拟合解决方法

文章目录返回传播计算方法神经网络整体架构&#xff08;暂时留存&#xff0c;等后面补&#xff09;神经元个数对结果的影响正则化与激活函数神经网络过拟合解决方法返回传播计算方法 实际上计算L&#xff08;损失值&#xff09;的时候并不是只是拿一组w来进行计算&#xff0c;…

用过MyBatis-Plus,我再也不想用mybatis了——MyBatis-Plus快速入门加常见注解总结,一文快速掌握MyBatis-Plus

相比与mybatis只做增强&#xff0c;不做修改 MyBatis-Plus学习笔记一&#xff0c;是什么二&#xff0c;入门案例1.建库建表2.创建spring Boot工程3.配置相关包及类4.测试三&#xff0c;基本的curd1.BaseMapper2.通用Service四.常用注解1.TableName2.TableId3TableField4.TableL…

【python】面向对象编程

文章目录一、函数大全1.1 匿名函数 lambda1.2 过滤函数 filter1.3 format1.4 try和except1.5 位置参数和关键字参数二、类与对象2.1创建对象2.2 封装的实现方式2.3 继承2.4方法重写2.5 object 类2.5.1 __str()__2.5.2 dict()2.5.3 len()2.5.4 add()2.5.5 new()init()2.6 多态的…

初识C语言(下)

写在前面 好了,现在我们开始C语言的第二个部分.今天我们需要看下面几个知识点,都是非常简单的,我们主要认识一下. 数组 我们知道一个一个属性可以用一个类型去表示,那么我想问的是如果是一个属性的多个呢?也就是多个一样的东西,此时我们就要使用数组来进行表示,所谓的数组就…

22. 输入和输出

1. 输出格式美化 (1) 如果你希望输出的形式更加多样&#xff0c;可以使用 str.format() 函数来格式化输出值。 (2) 如果你希望将输出的值转成字符串&#xff0c;可以使用 repr() 或 str() 函数来实现。   str()&#xff1a; 函数返回一个用户易读的表达形式。   repr()&am…

产品原型设计方法

产品原型设计方法1. 色彩选择与按钮设计1.1色彩选择1.2 按钮设计2. 使用原型设计中的基础元素2.1 使用文字元素2.2 使用图标元素3. 设计导航菜单栏和卡片式布局3.1设计导航菜单栏4.3 设计卡片式布局4. 使用UI框架4.1 使用UI框架的好处4.2 常用的UI框架1. 色彩选择与按钮设计 1…

K8s:通过 kubectl 插件 Kubepug 实现集群升级检查(废弃API资源检查)

写在前面 分享一个小工具&#xff0c;可用于 版本升级的 废弃 API 对象检查博文内容涉及&#xff1a; kubepug 离线安装&#xff0c;配置 kubectl 插件kubepug 两种方式离线使用 Demo 理解不足小伙伴帮忙指正 昔我往矣&#xff0c;杨柳依依。今我来思&#xff0c;雨雪霏霏。 —…

【HBase入门】1. HBase基础

简介 Hadoop 从 1970 年开始&#xff0c;大多数的公司数据存储和维护使用的是关系型数据库大数据技术出现后&#xff0c;很多拥有海量数据的公司开始选择像Hadoop的方式来存储海量数据Hadoop使用分布式文件系统HDFS来存储海量数据&#xff0c;并使用 MapReduce 来处理。Hadoo…

【Ajax】同源策略、跨域和JSONP

一、同源策略什么是同源如果两个页面的协议&#xff0c;域名和端口都相同&#xff0c;则两个页面具有相同的源。例如&#xff0c;下表给出了相对于 http://www.test.com/index.html 页面的同源检测&#xff08;如果没有写端口号&#xff0c;默认是80&#xff09;&#xff1a;UR…

开篇点睛——Elasticsearch

在互联网当中我们的查询的信息主要包括文章、视频、图片、网站信息等各式各样的复杂海量信息。怎么才能快速、准确的检索到我们想要的信息呢? 传统意义上根据数据的格式&#xff0c;我们会将数据分为三个大类 结构化数据非结构化数据半结构化数据 接下来我们详细的了解一下这…

Day07 - 面向对象

1. 面向对象概述 面向对象是一种对现实世界理解和抽象的方法&#xff0c;是计算机编程技术发展到一定阶段后的产物。 面向对象是相对于面向过程来讲的&#xff0c; 面向对象方法 &#xff0c;把相关的数据和方法组织为一个整体来看待&#xff0c;从更高的层次来进行系统建模&a…