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>未被实例化,找不到详细的定义。所以假设我们还是想沿用经得
起历史考验的“经典模型”时。就须要自己去显示实例化。
“显示实例化”的详细形式非常easy:仅仅要在模版定义的.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++基于该模型模板包括节目外实例的更多相关文章
- JS组件系列——基于Bootstrap Ace模板的菜单Tab页效果优化
前言:之前发表过一篇 JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享(你值得拥有) ,收到很多园友的反馈,当然也包括很多诟病,因为上篇只是将功能实现了,很多细节都没有处理 ...
- 微软BI 之SSAS 系列 - 基于雪花模型的维度设计
基于雪花模型的维度以下面的 Product 产品与产品子类别,产品类别为例. DimProduct 表和 DimProductSubcategory 表有外键关系,而 DimProductSubcat ...
- AIOps探索:基于VAE模型的周期性KPI异常检测方法——VAE异常检测
AIOps探索:基于VAE模型的周期性KPI异常检测方法 from:jinjinlin.com 作者:林锦进 前言 在智能运维领域中,由于缺少异常样本,有监督方法的使用场景受限.因此,如何利用无监 ...
- Halcon编程-基于形状特征的模板匹配
halcon软件最高效的一个方面在于模板匹配,号称可以快速进行柔性模板匹配,能够非常方便的用于缺陷检测.目标定位.下面以一个简单的例子说明基于形状特征的模板匹配. 为了在右图中,定位图中的三 ...
- 中国快递包裹总量的预测-基于SARIMA模型
code{white-space: pre;} pre:not([class]) { background-color: white; }if (window.hljs && docu ...
- 基于RBAC模型的通用企业权限管理系统
1. 为什么我们需要基于RBAC模型的通用企业权限管理系统 管理信息系统是一个复杂的人机交互系统,其中每个具体环节都可能受到安全威胁.构建强健的权限管理系统,保证管理信息系统的安全性是十分重要的.权限 ...
- UML和模式应用4:初始阶段(4)--需求制品之用例模型模板示例
1. 前言 UP开发包括四个阶段:初始阶段.细化阶段.构建阶段.移交阶段: UP每个阶段包括 业务建模.需求.设计等科目: 其中需求科目对应的需求制品包括:设想.业务规则.用例模型.补充性规格说明.词 ...
- ASP.NET MVC —— Model之一模型模板
http://www.cnblogs.com/lzhp/archive/2013/03/25/2981650.html Mvc model系列文章主要分为三部分:Model Templates,Mod ...
- 基于EPOLL模型的局域网聊天室和Echo服务器
一.EPOLL的优点 在Linux中,select/poll/epoll是I/O多路复用的三种方式,epoll是Linux系统上独有的高效率I/O多路复用方式,区别于select/poll.先说sel ...
随机推荐
- linux的tr命令
tr(translate缩写)主要用于删除文件中的控制字符,或进行字符转换. 语法 tr [ -c | -cds | -cs | -C | -Cds | -Cs | -ds | -s] [ -A] S ...
- HTML5:footer定位(底部+居中)的探讨+div图片居中问题
初学HTML+CSS布局,尝试自己写一个百度首页,可是footer的定位遇到麻烦而且百度没有好的解决方法,在此记录下逐步的过程.记录之,备忘. 初学,解决方法难免出现不妥之处,也请看到这篇文章的前辈指 ...
- 使用MSPT实现二层冗余
- 〖Groovy〗语言使用贴士(Tips)(转)
[Groovy]是一门运行在[JVM]之上的动态语言.由[James Strachan]和[Bob McWhirter]于2003年启动开发,之后于2004年3月成为[JSR 241](Java Sp ...
- 牛逼的验证码,printf返回值
牛逼的验证码,如下图, 结果是4321,为什么呢,主要是printf返回值问题?那么printf到底返回什么? 经查阅,printf的返回值是打印的字符个数,因此结果是4321就很明显了.
- Mysql 双向关联触发器
双向关联触发器 //增加 delimiter // create trigger InsertDemo AFTER insert on vaccine.demo for each row Begin ...
- 详解CMS垃圾回收机制
原创不易,未经允许,不得转载~~~ 什么是CMS? Concurrent Mark Sweep. 看名字就知道,CMS是一款并发.使用标记-清除算法的gc. CMS是针对老年代进行回收的GC. CMS ...
- ecshop模板 lbi文件
Ecshop根目录/ |->其它目录|->themes |->例:default (模板项目目录) |->images ...
- JS CSS 网页 简单 右侧 悬浮
<!--右侧效果--> <script> $().ready(function() { $(".orm").hover(function() { $(thi ...
- centos一些命令
1.查看系统使用端口并释放端口 [root@my_nn_01 WEB-INF]# lsof -w -n -i tcp:80 COMMAND PID USER FD TYPE DEVICE ...