C++模版基于包含模型之外的显示实例化

一、“经典模型”的失效

我们学过C++的人都知道,在C++中组织代码的经典模型是:将函数或类的声明和定义部分分开在不同的文件之中   ,

即一般将声明放在一个.h的头文件中而定义在放在一个.cpp文件之中,当然这的确是写代码的一种很优良的风格,但问题

是如果将这种“经典模型”应用到模版上时就会发生连接上错误。

例如:

文件“A.h”

#include"iostream"
using namespace std;
#pragma once
template<typename T>
class A
{
private:
	T t;
public:
	A(T d)
	{t = d;}
	~A(void){}
	void fun();
};

文件“A.cpp”

#include "A.h"
#include"iostream"
using namespace std;
template<typename T>
void A<T>::fun()
{
	cout<<t<<"这个是A类"<<endl;
}

主文件main.cpp:

#include<iostream>
#include"A.h"
using namespace std;

int main()
{
	A<int> a(1);
	a.fun();
}

将上面的程序编译连接运行,会发现编译通过,但连接会报错。

上述这种“经典模型”不再适用与C++模版的主要原因是:模版类或模版函数与一般的C++类或函数不同,对于模版

类或模版函数只有在遇到不同类型的应用时才会实例化出具体不同的函数或类,所以上面的程序连接错误的主要原因是

:模版类A未被实例化,编译器会分别的去编译那三个文件,因为A的定义和A的调用分别处在不同的.cpp文件中,所以当

A.cpp被编译时因未见到具体类型调用所以没实例化;而main.cpp在编译时编译器只从A.h看到了A类的声明,所以编译

器会假设程序在别的地方提供了A的具体定义,所以也没有实例化A。以至于在连接过程中发现A<int>没有被实例化的定

义而最终报错。

二、“包含模型”的出现

“包含模型”解决了上述问题,即将模版类的定义和声明都写在同一个.h文件即可。这样只要主文件包含了这个.h头文件

则在主文件编译时就会从该.h文件中找到模版类或函数的定义从而产生实例化。

例如:文件“A.h”

#include"iostream"
using namespace std;
#pragma once
template<typename T>
class A
{
private:
	T t;
public:
	A(T d)
	{t = d;}
	~A(void){}
	void fun()
	{
	cout<<t<<"这个是A类"<<endl;
	}
};

主文件“main.cpp”

#include<iostream>
#include"A.h"
using namespace std;

int main()
{
	A<int> a(1);
	a.fun();
}

可以运行通过。

三、显示实例化

显示实例化的出现主要是为了模版代码的组织形式的更加灵活性,同时也是对于“包含模型”的某些缺点的弥补,

在“包含模型”中有一个很大的不足就是:将所有的代码都写入一个.h头文件中这会明显的增加头文件的开销,且同时

对于应用该模版的每一个.cpp文件来说都要把此.h文件包含进去,显然这样做会更进一步的使整个程序的开销变的很

大,所以解决这个问题的一个办法就是“显示实例化”。

在最上面的那个例子中连接报错的原因是A<int>未被实例化,找不到具体的定义。所以如果我们还是想沿用经得

起历史考验的“经典模型”时,就需要自己去显示实例化。

“显示实例化”的具体形式很简单:只要在模版定义的.cpp文件中加上一句有显示实例化指示符template引导的需要

实例化实体的声明即可。

例如:对于最上面的例子:再要在A.cpp中在上下面的声明即可:

template A<int>;

例如完整例子修改后如下:

文件“A.h”

#include"iostream"
using namespace std;
#pragma once
template<typename T>
class A
{
private:
	T t;
public:
	A(T d)
	{t = d;}
	~A(void){}
	void fun();
};

文件“A.cpp”

#include "A.h"
#include"iostream"
using namespace std;
template A<int>;//显示实例化
template<typename T>
void A<T>::fun()
{
	cout<<t<<"这个是A类"<<endl;
}

主文件“mian.cpp”

#include<iostream>
#include"A.h"
using namespace std;

int main()
{
	A<int> a(1);
	a.fun();
}

运行通过!

四、“包含模型”与“显示实例化”的结合

其实“显示实例化”也有其自己的弊端,那就是对于模版类或模版函数的某一个具体类型的显示实例化必须唯一,不能重复

实例化,这也就是说在程序中你必须自己去跟踪模版的每一个实例化,否则就会出错。这样的问题在达到一定规模的大程序中

是相当困难的,所以将“包含模型”与“显示实例化”结合就是取各自之长,可以根据具体问题的要求而随意选择不同的模型。

具体的做法是:任然将模版的定义和声明都分开写在两个不同的文件,但这两个文件都必须是.h的头文件,且定义文件要

用#include包含声明文件。所以当自己希望使用“包含模型”时,只需要把定义文件.h包含在应用.cpp文件即可。而当自己需要使用

”显示实例化“时,只需要将声明.h文件包含在应用文件之中,并且同时在模版定义.h文件之中显示实例化所需要的具体实例即可。

C++模版基于包含模型之外的显示实例化,布布扣,bubuko.com

时间: 2024-10-27 08:19:53

C++模版基于包含模型之外的显示实例化的相关文章

基于乐理模型的算法作曲研究

Abstraction Musical composition is a sophisticated movement of thought that is unique for humans. More concretely, composition reflects the basic technology and theory of music, i.e. harmonics, polyphony, orchestration, structure and so on, which are

一种基于RBAC模型的动态访问控制改进方法

本发明涉及一种基于RBAC模型的动态访问控制改进方法,属于访问控制领域.对原有RBAC模型进行了权限的改进和约束条件的改进,具体为将权限分为静态权限和动态权限,其中静态权限是非工作流的权限,动态权限是工作流中的权限:将约束条件分为静态约束和动态约束,其中静态约束包括最小权限约束和职责分离约束,动态约束使动态权限按照工作流进行操作.采用本发明的方法改进后的RBAC模型具有以下优势:为传统的RBAC模型中增加了动态特性:跟纯动态模型相比较具有更高的效率:保证需要按顺序执行的权限能够按顺序执行,使得系

论文研读1.1 基于 DeepFM 模型的广告推荐系统研究(郁等)

基于 DeepFM 模型的广告推荐系统研究(郁等) 摘要 信息呈指数爆炸增长的时代,如何在这个信息千变万化的世界里获得用户想要的数据显得尤其重要.作者们提出了DeepFM模型并且实验结果发现,DeepFM模型比逻辑回归和因子分解机模型的效果都要好. 关键词 DeepFM 特征提取 广告推荐 深度神经网络 因子分解机 引言 海量信息与人难以获得准确信息的矛盾现状 广告推荐问题一般可理解为广告点击率问题(基于用户行为的预测问题).难以解决的问题:数据量大.数据稀疏.异常数据等.复杂模型训练难度大,容

京东评论情感分类器(基于bag-of-words模型)

最近在本来在研究paraVector模型,想拿bag-of-words来做对比. 数据集是京东的评论,经过人工挑选,选出一批正面和负面的评论. 实验的数据量不大,340条正面,314条负面.我一般拿200正面和200负面做训练,剩下做测试. 做着做着,领悟了一些机器学习的道理.发现,对于不同的数据集,效果是不同的. 对于特定的数据集,随便拿来一套模型可能并不适用. 对于这些评论,我感觉就是bag-of-words模型靠谱点. 因为这些评论的特点是语句简短,关键词重要. paraVector模型感

Spring基于事件驱动模型的订阅发布模式代码实例详解

代码下载地址:http://www.zuidaima.com/share/1791499571923968.htm 原文:Spring基于事件驱动模型的订阅发布模式代码实例详解 事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型:理解它的几个关键点: 首先是一种对象间的一对多的关系:最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方): 当目标发送改变(发布),观察者(订阅者)就可以接收到改变: 观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的

基于Select模型的混乱聊天室v1.0

最近在无聊完成了一个简单的基于select模型的匿名聊天室程序,均使用C++开发 服务器工作原理: 每接收一条客户端的信息,就将遍历所有的socket,并将该信息发给所有的客户端. 客户端使用两条线程,一个是接收服务端信息的线程,一个是等待阻塞输入的线程,获得输入时,将输入发送到服务器. 项目源码:https://github.com/coderguang/Chat 版本为v2.0的release. 其中ComLib也在github上 服务器核心代码: int main(int argc,cha

基于jQuery实现文字倾斜显示代码

这是一款基于jQuery实现文字倾斜显示,这是一款基于jQuery实现的超酷动态文字显示效果.适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗. 效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="container"> <div class="logo"> <img src="images/frame.png" alt=

《BI项目笔记》基于雪花模型的维度设计

原文:<BI项目笔记>基于雪花模型的维度设计 GBGradeCode 外键关系: 1 烟叶等级 T_GBGradeCode.I_DistinctionID=T_Distinction.I_DistinctionID 烟叶等级分为:上等烟.中等烟.下等烟.末等烟.低等烟.低次等烟.其它.下低等烟 2 分级标准 T_GBGradeCode.I_GradStanCode=T_GradeStandard.I_GradStanCode 取值为:四十二级.二十八级.自定义.其他.工艺级别 3 烟叶烤型 T

大前端学习笔记整理【一】CSS盒模型与基于盒模型的6种元素居中方案

概览 CSS盒模型,规定了元素框来处理元素的 内容.内边距.边框和外边距的方式 元素部分是指内容部分,也是最实际的内容,包围内容的称之为内边距,内边距外围是边框,边框外围就是外边距:且外边距是透明的,所以并不会阻挡其后的元素 * { margin: 0; padding: 0; } 这是在CSS中最常见的初始化CSS的代码,用于覆盖浏览器的默认样式 浏览器兼容性 大多数浏览器都会按照上面的图示来呈现内容.然而 IE 5 和 6 的呈现却是不正确的.根据 W3C 的规范,元素内容占据的空间是由 w