一个、“经典模式”失败

我们学过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++基于该模型模板包括节目外实例的更多相关文章

  1. JS组件系列——基于Bootstrap Ace模板的菜单Tab页效果优化

    前言:之前发表过一篇  JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享(你值得拥有) ,收到很多园友的反馈,当然也包括很多诟病,因为上篇只是将功能实现了,很多细节都没有处理 ...

  2. 微软BI 之SSAS 系列 - 基于雪花模型的维度设计

    基于雪花模型的维度以下面的 Product 产品与产品子类别,产品类别为例. DimProduct 表和 DimProductSubcategory 表有外键关系,而 DimProductSubcat ...

  3. AIOps探索:基于VAE模型的周期性KPI异常检测方法——VAE异常检测

    AIOps探索:基于VAE模型的周期性KPI异常检测方法 from:jinjinlin.com   作者:林锦进 前言 在智能运维领域中,由于缺少异常样本,有监督方法的使用场景受限.因此,如何利用无监 ...

  4. Halcon编程-基于形状特征的模板匹配

    halcon软件最高效的一个方面在于模板匹配,号称可以快速进行柔性模板匹配,能够非常方便的用于缺陷检测.目标定位.下面以一个简单的例子说明基于形状特征的模板匹配.      为了在右图中,定位图中的三 ...

  5. 中国快递包裹总量的预测-基于SARIMA模型

    code{white-space: pre;} pre:not([class]) { background-color: white; }if (window.hljs && docu ...

  6. 基于RBAC模型的通用企业权限管理系统

    1. 为什么我们需要基于RBAC模型的通用企业权限管理系统 管理信息系统是一个复杂的人机交互系统,其中每个具体环节都可能受到安全威胁.构建强健的权限管理系统,保证管理信息系统的安全性是十分重要的.权限 ...

  7. UML和模式应用4:初始阶段(4)--需求制品之用例模型模板示例

    1. 前言 UP开发包括四个阶段:初始阶段.细化阶段.构建阶段.移交阶段: UP每个阶段包括 业务建模.需求.设计等科目: 其中需求科目对应的需求制品包括:设想.业务规则.用例模型.补充性规格说明.词 ...

  8. ASP.NET MVC —— Model之一模型模板

    http://www.cnblogs.com/lzhp/archive/2013/03/25/2981650.html Mvc model系列文章主要分为三部分:Model Templates,Mod ...

  9. 基于EPOLL模型的局域网聊天室和Echo服务器

    一.EPOLL的优点 在Linux中,select/poll/epoll是I/O多路复用的三种方式,epoll是Linux系统上独有的高效率I/O多路复用方式,区别于select/poll.先说sel ...

随机推荐

  1. 伤不起的戴尔台式机XPS8700脆弱的蓝牙

    http://en.community.dell.com/support-forums/desktop/f/3514/t/19520747.aspx 1.报价仅仅包含主机,并且不带音响(speaker ...

  2. SE 2014年4月1日

    一. 描述OSPF报文都有哪些,其作用? OSPF报文主要有:hello报文.DD报文.LSR报文.LSU报文和LSAck报文. Hello报文主要用来建立和维护邻居关系. DD报文是链路状态数据库的 ...

  3. Python数据结构之注意事项

    1.列表 列表是Python中使用最频繁的数据结构,列表提供很多函数操作,比如下标存取,分片,index,append,remove等等. 例如:  list=[1,2,'hello','python ...

  4. poj3140(树的dfs)

    题目链接:http://poj.org/problem?id=3140 题意:给定一棵n棵节点的树,求删去某条边后两个分支的最小差异值. 分析:num[u]表示以u点为根节点的子树的总人数,那么不在该 ...

  5. 【剑指offer】旋转数组的最小值

    採用二分查找的策略,重点要考虑一些边界情况:旋转了0元素.即输入的是一个升序排列的数组.仅仅包括一个数字的数组.有非常多反复数字的数组等. AC代码: #include<stdio.h> ...

  6. CSDN开源夏令营 百度数据可视化实践 ECharts(8)问题分析

    ECharts问题描写叙述: 问题就是折线图上的点是显示的,有人问能不能一開始不显示,当你点击的时候或者是当鼠标移动到上面的时候,折线上的点才显示? 例如以下图所看到的: 分析:让折线上的点不显示能够 ...

  7. AlarmManager的学习与实现

    综述     这个类提供了一种使用系统提供的alarm服务.这个服务同意用户安排他们的应用程序在将来的某一个时间点执行.当设置的alarm响起,那么之前系统为这个alarm注冊的Intent就会自己主 ...

  8. Hot Days Codeforces Round #132 (Div. 2) D(贪婪)

    Description The official capital and the cultural capital of Berland are connected by a single road ...

  9. java 类 及其 执行过程

    java 类 命名 java类文件中  只能有一个公开类  且 公开类类名与当前类文件的文件名一致 方法如果使用了static修饰,那么此方法是类方法,可以 类名.方法名 使用. 你的main方法在同 ...

  10. HUNNU11351:Pythagoras's Revenge

    http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11351&courseid=0 Problem des ...